]> granicus.if.org Git - clang/commitdiff
Some builtins do not evaluate their arguments. Teach EvaluatedExprVisitor not
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 17 Jan 2013 23:46:04 +0000 (23:46 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 17 Jan 2013 23:46:04 +0000 (23:46 +0000)
to visit them.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172769 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/EvaluatedExprVisitor.h
include/clang/AST/Expr.h
include/clang/Basic/Builtins.def
include/clang/Basic/Builtins.h
lib/AST/Expr.cpp
test/SemaCXX/warn-unsequenced.cpp

index 6e6f3176ff6c66860427e68bd8f37aa08569252a..eb186c217e357648b34384a82b097e8b7e234eb1 100644 (file)
@@ -61,12 +61,17 @@ public:
     // expressions.
     return this->Visit(E->getInit());
   }
-  
+
   void VisitCXXTypeidExpr(CXXTypeidExpr *E) {
     if (E->isPotentiallyEvaluated())
       return this->Visit(E->getExprOperand());
   }
-  
+
+  void VisitCallExpr(CallExpr *CE) {
+    if (!CE->isUnevaluatedBuiltinCall(Context))
+      return static_cast<ImplClass*>(this)->VisitExpr(CE);
+  }
+
   /// \brief The basis case walks all of the children of the statement or
   /// expression, assuming they are all potentially evaluated.
   void VisitStmt(Stmt *S) {
index 10bb3531018a6903eccdb4f6ec67a63c1e94e323..5b6e6608322ff46aba15b5028b5a3230281aac22 100644 (file)
@@ -2193,6 +2193,10 @@ public:
   /// not, return 0.
   unsigned isBuiltinCall() const;
 
+  /// \brief Returns \c true if this is a call to a builtin which does not
+  /// evaluate side-effects within its arguments.
+  bool isUnevaluatedBuiltinCall(ASTContext &Ctx) const;
+
   /// getCallReturnType - Get the return type of the call expr. This is not
   /// always the type of the expr itself, if the return type is a reference
   /// type.
index 63fca6f9cc7d1f945acfe0aa6975d7167c00fee8..0a513efdbc16be2213b5570da950e256b53b1419 100644 (file)
@@ -82,6 +82,7 @@
 //          through an ellipsis
 //  e -> const, but only when -fmath-errno=0
 //  j -> returns_twice (like setjmp)
+//  u -> arguments are not evaluated for their side-effects
 //  FIXME: gcc has nonnull
 
 #if defined(BUILTIN) && !defined(LIBBUILTIN)
@@ -395,8 +396,8 @@ BUILTIN(__builtin_bswap32, "UiUi", "nc")
 BUILTIN(__builtin_bswap64, "ULLiULLi", "nc")
 
 // Random GCC builtins
-BUILTIN(__builtin_constant_p, "i.", "nct")
-BUILTIN(__builtin_classify_type, "i.", "nct")
+BUILTIN(__builtin_constant_p, "i.", "nctu")
+BUILTIN(__builtin_classify_type, "i.", "nctu")
 BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc")
 BUILTIN(__builtin___NSStringMakeConstantString, "FC*cC*", "nc")
 BUILTIN(__builtin_va_start, "vA.", "nt")
@@ -454,7 +455,7 @@ BUILTIN(__builtin_dwarf_sp_column, "Ui", "n")
 BUILTIN(__builtin_extend_pointer, "ULLiv*", "n") // _Unwind_Word == uint64_t
 
 // GCC Object size checking builtins
-BUILTIN(__builtin_object_size, "zvC*i", "n")
+BUILTIN(__builtin_object_size, "zvC*i", "nu")
 BUILTIN(__builtin___memcpy_chk, "v*v*vC*zz", "nF")
 BUILTIN(__builtin___memccpy_chk, "v*v*vC*izz", "nF")
 BUILTIN(__builtin___memmove_chk, "v*v*vC*zz", "nF")
index 257daf10ecee0949e2aa1529a51047bbe67222a4..3b88e1550cba911fae74625d2725b4b36e84ac5c 100644 (file)
@@ -109,6 +109,12 @@ public:
     return strchr(GetRecord(ID).Attributes, 'j') != 0;
   }
 
+  /// \brief Returns true if this builtin does not perform the side-effects
+  /// of its arguments.
+  bool isUnevaluated(unsigned ID) const {
+    return strchr(GetRecord(ID).Attributes, 'u') != 0;
+  }
+
   /// \brief Return true if this is a builtin for a libc/libm function,
   /// with a "__builtin_" prefix (e.g. __builtin_abs).
   bool isLibFunction(unsigned ID) const {
index 4796257c92dce9f9fca8e1a4d97eea43d193d8ef..718002f97d1e5a2e2011fdae61a899e73bdb560b 100644 (file)
@@ -1137,6 +1137,12 @@ unsigned CallExpr::isBuiltinCall() const {
   return FDecl->getBuiltinID();
 }
 
+bool CallExpr::isUnevaluatedBuiltinCall(ASTContext &Ctx) const {
+  if (unsigned BI = isBuiltinCall())
+    return Ctx.BuiltinInfo.isUnevaluated(BI);
+  return false;
+}
+
 QualType CallExpr::getCallReturnType() const {
   QualType CalleeType = getCallee()->getType();
   if (const PointerType *FnTypePtr = CalleeType->getAs<PointerType>())
index 15ca1dba7a80f851e48438e963b61e39f0fcf2a7..c7acfca6db3102a49de5178a110e3f9e32c82871 100644 (file)
@@ -95,4 +95,9 @@ void test() {
 
   xs[8] && (++a + a++); // expected-warning {{multiple unsequenced modifications}}
   xs[8] || (++a + a++); // expected-warning {{multiple unsequenced modifications}}
+
+  (__builtin_classify_type(++a) ? 1 : 0) + ++a; // ok
+  (__builtin_constant_p(++a) ? 1 : 0) + ++a; // ok
+  (__builtin_object_size(&(++a, a), 0) ? 1 : 0) + ++a; // ok
+  (__builtin_expect(++a, 0) ? 1 : 0) + ++a; // expected-warning {{multiple unsequenced modifications}}
 }