Add initial support for constant CFStrings.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41136 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Sema/SemaChecking.cpp b/Sema/SemaChecking.cpp
index 511f56f..ed4c898 100644
--- a/Sema/SemaChecking.cpp
+++ b/Sema/SemaChecking.cpp
@@ -28,7 +28,7 @@
/// CheckFunctionCall - Check a direct function call for various correctness
/// and safety properties not strictly enforced by the C type system.
-void
+bool
Sema::CheckFunctionCall(Expr *Fn,
SourceLocation LParenLoc, SourceLocation RParenLoc,
FunctionDecl *FDecl,
@@ -37,10 +37,17 @@
// Get the IdentifierInfo* for the called function.
IdentifierInfo *FnInfo = FDecl->getIdentifier();
+ if (FnInfo->getBuiltinID() ==
+ Builtin::BI__builtin___CFStringMakeConstantString) {
+ assert(NumArgsInCall == 1 &&
+ "Wrong number of arguments to builtin CFStringMakeConstantString");
+ return CheckBuiltinCFStringArgument(Args[0]);
+ }
+
// Search the KnownFunctionIDs for the identifier.
unsigned i = 0, e = id_num_known_functions;
for (; i != e; ++i) { if (KnownFunctionIDs[i] == FnInfo) break; }
- if (i == e) return;
+ if (i == e) return true;
// Printf checking.
if (i <= id_vprintf) {
@@ -66,6 +73,46 @@
CheckPrintfArguments(Fn, LParenLoc, RParenLoc, HasVAListArg,
FDecl, format_idx, Args, NumArgsInCall);
}
+
+ return true;
+}
+
+/// CheckBuiltinCFStringArgument - Checks that the argument to the builtin
+/// CFString constructor is correct
+bool Sema::CheckBuiltinCFStringArgument(Expr* Arg)
+{
+ while (ParenExpr *PE = dyn_cast<ParenExpr>(Arg))
+ Arg = PE->getSubExpr();
+
+ StringLiteral *Literal = dyn_cast<StringLiteral>(Arg);
+
+ if (!Literal || Literal->isWide()) {
+ Diag(Arg->getLocStart(),
+ diag::err_cfstring_literal_not_string_constant,
+ Arg->getSourceRange());
+ return false;
+ }
+
+ const char *Data = Literal->getStrData();
+ unsigned Length = Literal->getByteLength();
+
+ for (unsigned i = 0; i < Length; ++i) {
+ if (!isascii(Data[i])) {
+ Diag(PP.AdvanceToTokenCharacter(Arg->getLocStart(), i + 1),
+ diag::warn_cfstring_literal_contains_non_ascii_character,
+ Arg->getSourceRange());
+ break;
+ }
+
+ if (!Data[i]) {
+ Diag(PP.AdvanceToTokenCharacter(Arg->getLocStart(), i + 1),
+ diag::warn_cfstring_literal_contains_nul_character,
+ Arg->getSourceRange());
+ break;
+ }
+ }
+
+ return true;
}
/// CheckPrintfArguments - Check calls to printf (and similar functions) for