aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-09-10 06:27:15 +0000
committerDouglas Gregor <dgregor@apple.com>2010-09-10 06:27:15 +0000
commit5726d405e71f11feaaf0c8f518abe26e909537a4 (patch)
tree6cea51e0bebf26f8b1f1703b6c7282fa41b1febd
parent942e24d0ca23ebd9a8d8a180d35dad237235b94a (diff)
Support strlen() and __builtin_strlen() as constant expressions with
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
-rw-r--r--lib/AST/ExprConstant.cpp18
-rw-r--r--test/Sema/constant-builtins-2.c4
2 files changed, 22 insertions, 0 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 04aea9e9b9..7736581738 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -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);
}
}
diff --git a/test/Sema/constant-builtins-2.c b/test/Sema/constant-builtins-2.c
index 23aa314e0c..68b46bf19a 100644
--- a/test/Sema/constant-builtins-2.c
+++ b/test/Sema/constant-builtins-2.c
@@ -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];