]> granicus.if.org Git - clang/commitdiff
Add Builtins.def attribute for "can be a constant expression".
authorDaniel Dunbar <daniel@zuster.org>
Thu, 2 Oct 2008 23:30:31 +0000 (23:30 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Thu, 2 Oct 2008 23:30:31 +0000 (23:30 +0000)
 - Enabled for builtins which are always constant expressions
   (__builtin_huge_val*, __builtin_inf*, __builtin_constant_p,
   __builtin_classify_type, __builtin___CFStringMakeConstantString).

Added Builtin::Context::isConstantExpr.
 - Currently overly simply interface which only works for builtins
   whose constantexprness does not depend on their arguments.

CallExpr::isBuiltinConstantExpr now takes an ASTContext argument.

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

include/clang/AST/Builtins.def
include/clang/AST/Builtins.h
include/clang/AST/Expr.h
lib/AST/Expr.cpp
lib/Sema/SemaDecl.cpp
test/Sema/constant-builtins.c [new file with mode: 0644]

index d23cc14eb92b2f62389f74c02bbd4fc098999ad4..c993a75377481debffe0e8c32d60b699f4a7f140 100644 (file)
 //  n -> nothrow
 //  c -> const
 //  F -> this is a libc/libm function with a '__builtin_' prefix added.
+//  C -> this builtin can be used as a "constant expression"
 //  FIXME: gcc has nonnull
 
 // Standard libc/libm functions:
-BUILTIN(__builtin_huge_val, "d", "nc")
-BUILTIN(__builtin_huge_valf, "f", "nc")
-BUILTIN(__builtin_huge_vall, "Ld", "nc")
-BUILTIN(__builtin_inf  , "d"   , "nc")
-BUILTIN(__builtin_inff , "f"   , "nc")
-BUILTIN(__builtin_infl , "Ld"  , "nc")
+BUILTIN(__builtin_huge_val, "d", "ncC")
+BUILTIN(__builtin_huge_valf, "f", "ncC")
+BUILTIN(__builtin_huge_vall, "Ld", "ncC")
+BUILTIN(__builtin_inf  , "d"   , "ncC")
+BUILTIN(__builtin_inff , "f"   , "ncC")
+BUILTIN(__builtin_infl , "Ld"  , "ncC")
 BUILTIN(__builtin_nan,  "dcC*" , "ncF")
 BUILTIN(__builtin_nanf, "fcC*" , "ncF")
 BUILTIN(__builtin_nanl, "LdcC*", "ncF")
@@ -111,9 +112,9 @@ BUILTIN(__builtin_bswap32, "UiUi", "nc")
 BUILTIN(__builtin_bswap64, "ULLiULLi", "nc")
 
 // Random GCC builtins
-BUILTIN(__builtin_constant_p, "UsUs", "nc")
-BUILTIN(__builtin_classify_type, "i.", "nc")
-BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc")
+BUILTIN(__builtin_constant_p, "UsUs", "ncC")
+BUILTIN(__builtin_classify_type, "i.", "ncC")
+BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "ncC")
 BUILTIN(__builtin_va_start, "va&.", "n")
 BUILTIN(__builtin_va_end, "va&", "n")
 BUILTIN(__builtin_va_copy, "va&a", "n")
index 0deaca6a68c00650d2af7e5c2a3e73af93abb6de..10805fa0fa6dfb27143c52c1216b4e0889aa727d 100644 (file)
@@ -73,11 +73,17 @@ public:
   }
   
   /// isLibFunction - Return true if this is a builtin for a libc/libm function,
-  /// with a "__builtin_" prefix (e.g. __builtin_inf).
+  /// with a "__builtin_" prefix (e.g. __builtin_abs).
   bool isLibFunction(unsigned ID) const {
     return strchr(GetRecord(ID).Attributes, 'F') != 0;
   }
   
+  /// isConstantExpr - Return true if this builtin can be used where a
+  /// constant expression is required.
+  bool isConstantExpr(unsigned ID) const {
+    return strchr(GetRecord(ID).Attributes, 'C') != 0;
+  }
+  
   /// hasVAListUse - Return true of the specified builtin uses __builtin_va_list
   /// as an operand or return type.
   bool hasVAListUse(unsigned ID) const {
index 16daa64a1c00f08e6e974c2b91d359f5332809e1..f7aa35174557786facbb2daf808c5daf99f352bd 100644 (file)
@@ -704,7 +704,7 @@ public:
   bool isBuiltinClassifyType(llvm::APSInt &Result) const;
 
   /// isBuiltinConstantExpr - Return true if this built-in call is constant.
-  bool isBuiltinConstantExpr() const;
+  bool isBuiltinConstantExpr(ASTContext &Ctx) const;
   
   SourceLocation getRParenLoc() const { return RParenLoc; }
 
index 6a4b6b0493d3ba431b52782b46c52f3f772c0a73..14b7b51ebb0213ce8772956ee6ba42c6e3351658 100644 (file)
@@ -139,7 +139,7 @@ void CallExpr::setNumArgs(unsigned NumArgs) {
   this->NumArgs = NumArgs;
 }
 
-bool CallExpr::isBuiltinConstantExpr() const {
+bool CallExpr::isBuiltinConstantExpr(ASTContext &Ctx) const {
   // All simple function calls (e.g. func()) are implicitly cast to pointer to
   // function. As a result, we try and obtain the DeclRefExpr from the 
   // ImplicitCastExpr.
@@ -159,10 +159,7 @@ bool CallExpr::isBuiltinConstantExpr() const {
   if (!builtinID)
     return false;
 
-  // We have a builtin that is a constant expression
-  return builtinID == Builtin::BI__builtin___CFStringMakeConstantString ||
-         builtinID == Builtin::BI__builtin_classify_type ||
-         builtinID == Builtin::BI__builtin_huge_valf;
+  return Ctx.BuiltinInfo.isConstantExpr(builtinID);
 }
 
 bool CallExpr::isBuiltinClassifyType(llvm::APSInt &Result) const {
@@ -585,7 +582,7 @@ bool Expr::isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const {
     return true;
   case CallExprClass: {
     const CallExpr *CE = cast<CallExpr>(this);
-    if (CE->isBuiltinConstantExpr())
+    if (CE->isBuiltinConstantExpr(Ctx))
       return true;
     if (Loc) *Loc = getLocStart();
     return false;
index 9c5c4f2d4bf5a071525c21408b093444c85f886c..8214fe4c631683951fbbfa6582ab7916d7953104 100644 (file)
@@ -878,7 +878,7 @@ bool Sema::CheckAddressConstantExpression(const Expr* Init) {
     return false;
   case Expr::CallExprClass: {
     const CallExpr *CE = cast<CallExpr>(Init);
-    if (CE->isBuiltinConstantExpr())
+    if (CE->isBuiltinConstantExpr(Context))
       return false;
     Diag(Init->getExprLoc(),
          diag::err_init_element_not_constant, Init->getSourceRange());
@@ -1077,7 +1077,7 @@ bool Sema::CheckArithmeticConstantExpression(const Expr* Init) {
     return false;
   case Expr::CallExprClass: {
     const CallExpr *CE = cast<CallExpr>(Init);
-    if (CE->isBuiltinConstantExpr())
+    if (CE->isBuiltinConstantExpr(Context))
       return false;
     Diag(Init->getExprLoc(),
          diag::err_init_element_not_constant, Init->getSourceRange());
diff --git a/test/Sema/constant-builtins.c b/test/Sema/constant-builtins.c
new file mode 100644 (file)
index 0000000..875414a
--- /dev/null
@@ -0,0 +1,18 @@
+// RUN: clang -fsyntax-only %s
+
+// Math stuff
+
+float        g0 = __builtin_huge_val();
+double       g1 = __builtin_huge_valf();
+long double  g2 = __builtin_huge_vall();
+float        g3 = __builtin_inf();
+double       g4 = __builtin_inff();
+long double  g5 = __builtin_infl();
+
+// GCC misc stuff
+
+extern int f();
+
+int h0 = __builtin_types_compatible_p(int,float);
+//int h1 = __builtin_choose_expr(1, 10, f());
+//int h2 = __builtin_expect(0, 0);