diff options
-rw-r--r-- | lib/AST/ExprConstant.cpp | 18 | ||||
-rw-r--r-- | test/Sema/constant-builtins-2.c | 4 |
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]; |