Index: clang/include/clang/Basic/DiagnosticGroups.td =================================================================== --- clang/include/clang/Basic/DiagnosticGroups.td +++ clang/include/clang/Basic/DiagnosticGroups.td @@ -99,6 +99,7 @@ DiagGroup<"float-conversion", [FloatOverflowConversion, FloatZeroConversion]>; +def FrameAddress : DiagGroup<"frame-address">; def DoublePromotion : DiagGroup<"double-promotion">; def EnumTooLarge : DiagGroup<"enum-too-large">; def UnsupportedNan : DiagGroup<"unsupported-nan">; @@ -868,6 +869,7 @@ DeleteNonVirtualDtor, Format, ForLoopAnalysis, + FrameAddress, Implicit, InfiniteRecursion, IntInBoolContext, Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1780,6 +1780,11 @@ def err_illegal_union_or_anon_struct_member : Error< "%select{anonymous struct|union}0 member %1 has a non-trivial " "%sub{select_special_member_kind}2">; + +def warn_frame_address : Warning< + "calling '%0' with a nonzero argument is unsafe">, + InGroup, DefaultIgnore; + def warn_cxx98_compat_nontrivial_union_or_anon_struct_member : Warning< "%select{anonymous struct|union}0 member %1 with a non-trivial " "%sub{select_special_member_kind}2 is incompatible with C++98">, Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -1851,6 +1851,17 @@ case Builtin::BI__builtin_return_address: if (SemaBuiltinConstantArgRange(TheCall, 0, 0, 0xFFFF)) return ExprError(); + + // -Wframe-address warning if non-zero passed to builtin + // return/frame address. + Expr::EvalResult Result; + if (TheCall->getArg(0)->EvaluateAsInt(Result, getASTContext()) && + Result.Val.getInt() != 0) + Diag(TheCall->getBeginLoc(), diag::warn_frame_address) + << ((BuiltinID == Builtin::BI__builtin_return_address) + ? "__builtin_return_address" + : "__builtin_frame_address") + << TheCall->getSourceRange(); break; } Index: clang/test/Misc/warning-wall.c =================================================================== --- clang/test/Misc/warning-wall.c +++ clang/test/Misc/warning-wall.c @@ -16,6 +16,7 @@ CHECK-NEXT: -Wformat-y2k CHECK-NEXT: -Wformat-invalid-specifier CHECK-NEXT: -Wfor-loop-analysis +CHECK-NEXT: -Wframe-address CHECK-NEXT: -Wimplicit CHECK-NEXT: -Wimplicit-function-declaration CHECK-NEXT: -Wimplicit-int Index: clang/test/Sema/builtin-returnaddress.c =================================================================== --- /dev/null +++ clang/test/Sema/builtin-returnaddress.c @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -Wframe-address -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wmost -verify %s + +void* a(unsigned x) { +return __builtin_return_address(0); +} + +void* b(unsigned x) { +return __builtin_return_address(1); // expected-warning{{calling '__builtin_return_address' with a nonzero argument is unsafe}} +} + +void* c(unsigned x) { +return __builtin_frame_address(0); +} + +void* d(unsigned x) { +return __builtin_frame_address(1); // expected-warning{{calling '__builtin_frame_address' with a nonzero argument is unsafe}} +} +