]> granicus.if.org Git - clang/commitdiff
Support strlen() and __builtin_strlen() as constant expressions with
authorDouglas Gregor <dgregor@apple.com>
Fri, 10 Sep 2010 06:27:15 +0000 (06:27 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 10 Sep 2010 06:27:15 +0000 (06:27 +0000)
the call argument is a string literal. Fixes
<rdar://problem/8413477>.

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

lib/AST/ExprConstant.cpp
test/Sema/constant-builtins-2.c

index 04aea9e9b9e65851408506a969c00defb968c142..773658173885aa36435ba01f0a537b91b77100eb 100644 (file)
@@ -1159,6 +1159,24 @@ bool IntExprEvaluator::VisitCallExpr(CallExpr *E) {
 
   case Builtin::BI__builtin_expect:
     return Visit(E->getArg(0));
+      
+  case Builtin::BIstrlen:
+  case Builtin::BI__builtin_strlen:
+    // As an extension, we support strlen() and __builtin_strlen() as constant
+    // expressions when the argument is a string literal.
+    if (StringLiteral *S
+               = dyn_cast<StringLiteral>(E->getArg(0)->IgnoreParenImpCasts())) {
+      // The string literal may have embedded null characters. Find the first
+      // one and truncate there.
+      llvm::StringRef Str = S->getString();
+      llvm::StringRef::size_type Pos = Str.find(0);
+      if (Pos != llvm::StringRef::npos)
+        Str = Str.substr(0, Pos);
+      
+      return Success(Str.size(), E);
+    }
+      
+    return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
   }
 }
 
index 23aa314e0c32e751196c72427fdba7ce01428886..68b46bf19ad90ea3cfa2ccd556004a3d45d6c931 100644 (file)
@@ -50,3 +50,7 @@ int h0 = __builtin_types_compatible_p(int, float);
 //int h2 = __builtin_expect(0, 0);
 extern long int bi0;
 extern __typeof__(__builtin_expect(0, 0)) bi0;
+
+// Strings
+int array1[__builtin_strlen("ab\0cd")];
+int array2[(sizeof(array1)/sizeof(int)) == 2? 1 : -1];