aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r--lib/Sema/SemaChecking.cpp77
1 files changed, 56 insertions, 21 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index b0d6901953..4bf8fc9dce 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -423,12 +423,13 @@ bool Sema::SemaBuiltinObjectSize(CallExpr *TheCall) {
}
// Handle i > 1 ? "x" : "y", recursivelly
-bool Sema::SemaCheckStringLiteral(Expr *E, CallExpr *TheCall, bool HasVAListArg,
+bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
+ bool HasVAListArg,
unsigned format_idx, unsigned firstDataArg) {
switch (E->getStmtClass()) {
case Stmt::ConditionalOperatorClass: {
- ConditionalOperator *C = cast<ConditionalOperator>(E);
+ const ConditionalOperator *C = cast<ConditionalOperator>(E);
return SemaCheckStringLiteral(C->getLHS(), TheCall,
HasVAListArg, format_idx, firstDataArg)
&& SemaCheckStringLiteral(C->getRHS(), TheCall,
@@ -436,26 +437,54 @@ bool Sema::SemaCheckStringLiteral(Expr *E, CallExpr *TheCall, bool HasVAListArg,
}
case Stmt::ImplicitCastExprClass: {
- ImplicitCastExpr *Expr = dyn_cast<ImplicitCastExpr>(E);
+ const ImplicitCastExpr *Expr = cast<ImplicitCastExpr>(E);
return SemaCheckStringLiteral(Expr->getSubExpr(), TheCall, HasVAListArg,
format_idx, firstDataArg);
}
case Stmt::ParenExprClass: {
- ParenExpr *Expr = dyn_cast<ParenExpr>(E);
+ const ParenExpr *Expr = cast<ParenExpr>(E);
return SemaCheckStringLiteral(Expr->getSubExpr(), TheCall, HasVAListArg,
format_idx, firstDataArg);
}
+
+ case Stmt::DeclRefExprClass: {
+ const DeclRefExpr *DR = cast<DeclRefExpr>(E);
+
+ // As an exception, do not flag errors for variables binding to
+ // const string literals.
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ bool isConstant = false;
+ QualType T = DR->getType();
+
+ if (const ArrayType *AT = Context.getAsArrayType(T)) {
+ isConstant = AT->getElementType().isConstant(Context);
+ }
+ else if (const PointerType *PT = T->getAsPointerType()) {
+ isConstant = T.isConstant(Context) &&
+ PT->getPointeeType().isConstant(Context);
+ }
+
+ if (isConstant) {
+ const VarDecl *Def = 0;
+ if (const Expr *Init = VD->getDefinition(Def))
+ return SemaCheckStringLiteral(Init, TheCall,
+ HasVAListArg, format_idx, firstDataArg);
+ }
+ }
+
+ return false;
+ }
- default: {
- ObjCStringLiteral *ObjCFExpr = dyn_cast<ObjCStringLiteral>(E);
- StringLiteral *StrE = NULL;
-
- if (ObjCFExpr)
+ case Stmt::ObjCStringLiteralClass:
+ case Stmt::StringLiteralClass: {
+ const StringLiteral *StrE = NULL;
+
+ if (const ObjCStringLiteral *ObjCFExpr = dyn_cast<ObjCStringLiteral>(E))
StrE = ObjCFExpr->getString();
else
- StrE = dyn_cast<StringLiteral>(E);
-
+ StrE = cast<StringLiteral>(E);
+
if (StrE) {
CheckPrintfString(StrE, E, TheCall, HasVAListArg, format_idx,
firstDataArg);
@@ -464,6 +493,9 @@ bool Sema::SemaCheckStringLiteral(Expr *E, CallExpr *TheCall, bool HasVAListArg,
return false;
}
+
+ default:
+ return false;
}
}
@@ -518,9 +550,9 @@ bool Sema::SemaCheckStringLiteral(Expr *E, CallExpr *TheCall, bool HasVAListArg,
///
/// For now, we ONLY do (1), (3), (5), (6), (7), and (8).
void
-Sema::CheckPrintfArguments(CallExpr *TheCall, bool HasVAListArg,
+Sema::CheckPrintfArguments(const CallExpr *TheCall, bool HasVAListArg,
unsigned format_idx, unsigned firstDataArg) {
- Expr *Fn = TheCall->getCallee();
+ const Expr *Fn = TheCall->getCallee();
// CHECK: printf-like function is called with no format string.
if (format_idx >= TheCall->getNumArgs()) {
@@ -529,7 +561,7 @@ Sema::CheckPrintfArguments(CallExpr *TheCall, bool HasVAListArg,
return;
}
- Expr *OrigFormatExpr = TheCall->getArg(format_idx)->IgnoreParenCasts();
+ const Expr *OrigFormatExpr = TheCall->getArg(format_idx)->IgnoreParenCasts();
// CHECK: format string is not a string literal.
//
@@ -567,22 +599,25 @@ Sema::CheckPrintfArguments(CallExpr *TheCall, bool HasVAListArg,
// if the argument is a DeclRefExpr that references a parameter. We'll
// add proper support for checking the attribute later.
if (HasVAListArg)
- if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(OrigFormatExpr))
+ if (const DeclRefExpr* DR = dyn_cast<DeclRefExpr>(OrigFormatExpr))
if (isa<ParmVarDecl>(DR->getDecl()))
return;
Diag(TheCall->getArg(format_idx)->getLocStart(),
diag::warn_printf_not_string_constant)
- << OrigFormatExpr->getSourceRange();
+ << OrigFormatExpr->getSourceRange();
return;
}
}
-void Sema::CheckPrintfString(StringLiteral *FExpr, Expr *OrigFormatExpr,
- CallExpr *TheCall, bool HasVAListArg, unsigned format_idx,
- unsigned firstDataArg) {
+void Sema::CheckPrintfString(const StringLiteral *FExpr,
+ const Expr *OrigFormatExpr,
+ const CallExpr *TheCall, bool HasVAListArg,
+ unsigned format_idx, unsigned firstDataArg) {
+
+ const ObjCStringLiteral *ObjCFExpr =
+ dyn_cast<ObjCStringLiteral>(OrigFormatExpr);
- ObjCStringLiteral *ObjCFExpr = dyn_cast<ObjCStringLiteral>(OrigFormatExpr);
// CHECK: is the format string a wide literal?
if (FExpr->isWide()) {
Diag(FExpr->getLocStart(),
@@ -673,7 +708,7 @@ void Sema::CheckPrintfString(StringLiteral *FExpr, Expr *OrigFormatExpr,
}
// Perform type checking on width/precision specifier.
- Expr *E = TheCall->getArg(format_idx+numConversions);
+ const Expr *E = TheCall->getArg(format_idx+numConversions);
if (const BuiltinType *BT = E->getType()->getAsBuiltinType())
if (BT->getKind() == BuiltinType::Int)
break;