[cfe-commits] r158949 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/Sema/SemaChecking.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaOverload.cpp test/SemaCXX/printf-block.cpp test/SemaCXX/printf-cstr.cpp
Rafael Espindola
rafael.espindola at gmail.com
Thu Jun 21 16:44:22 PDT 2012
Author: rafael
Date: Thu Jun 21 18:44:21 2012
New Revision: 158949
URL: http://llvm.org/viewvc/llvm-project?rev=158949&view=rev
Log:
Revert r158887. This fixes pr13168.
Revert "If an object (such as a std::string) with an appropriate c_str() member function"
This reverts commit 7d96f6106bfbd85b1af06f34fdbf2834aad0e47e.
Removed:
cfe/trunk/test/SemaCXX/printf-block.cpp
cfe/trunk/test/SemaCXX/printf-cstr.cpp
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaChecking.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=158949&r1=158948&r2=158949&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Jun 21 18:44:21 2012
@@ -4723,11 +4723,6 @@
"cannot pass object with interface type %0 by-value through variadic "
"%select{function|block|method}1">;
-def warn_non_pod_vararg_with_format_string : Warning<
- "cannot pass %select{non-POD|non-trivial}0 object of type %1 to variadic "
- "function; expected type from format string was %2">,
- InGroup<DiagGroup<"non-pod-varargs">>, DefaultError;
-
def warn_cannot_pass_non_pod_arg_to_vararg : Warning<
"cannot pass object of %select{non-POD|non-trivial}0 type %1 through variadic"
" %select{function|block|method|constructor}2; call will abort at runtime">,
@@ -5211,8 +5206,7 @@
"no closing ']' for '%%[' in scanf format string">,
InGroup<Format>;
def note_format_string_defined : Note<"format string is defined here">;
-def note_printf_c_str: Note<"did you mean to call the %0 method?">;
-
+
def warn_null_arg : Warning<
"null passed to a callee which requires a non-null argument">,
InGroup<NonNull>;
@@ -5672,3 +5666,4 @@
}
} // end of sema component.
+
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=158949&r1=158948&r2=158949&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Jun 21 18:44:21 2012
@@ -6409,21 +6409,6 @@
VariadicDoesNotApply
};
- VariadicCallType getVariadicCallType(FunctionDecl *FDecl,
- const FunctionProtoType *Proto,
- Expr *Fn);
-
- // Used for determining in which context a type is allowed to be passed to a
- // vararg function.
- enum VarArgKind {
- VAK_Valid,
- VAK_ValidInCXX11,
- VAK_Invalid
- };
-
- // Determines which VarArgKind fits an expression.
- VarArgKind isValidVarArgType(const QualType &Ty);
-
/// GatherArgumentsForCall - Collector argument expressions for various
/// form of call prototypes.
bool GatherArgumentsForCall(SourceLocation CallLoc,
@@ -6436,14 +6421,10 @@
bool AllowExplicit = false);
// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
- // will return ExprError() if the resulting type is not a POD type.
+ // will warn if the resulting type is not a POD type.
ExprResult DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
FunctionDecl *FDecl);
- /// Checks to see if the given expression is a valid argument to a variadic
- /// function, issuing a diagnostic and returning NULL if not.
- bool variadicArgumentPODCheck(const Expr *E, VariadicCallType CT);
-
// UsualArithmeticConversions - performs the UsualUnaryConversions on it's
// operands and then handles various conversions that are common to binary
// operators (C99 6.3.1.8). If both operands aren't arithmetic, this
@@ -7018,33 +6999,10 @@
const ArraySubscriptExpr *ASE=0,
bool AllowOnePastEnd=true, bool IndexNegated=false);
void CheckArrayAccess(const Expr *E);
- // Used to grab the relevant information from a FormatAttr and a
- // FunctionDeclaration.
- struct FormatStringInfo {
- unsigned FormatIdx;
- unsigned FirstDataArg;
- bool HasVAListArg;
- };
-
- bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
- FormatStringInfo *FSI);
- bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
- const FunctionProtoType *Proto);
+ bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall);
bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc,
Expr **Args, unsigned NumArgs);
- bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall,
- const FunctionProtoType *Proto);
- void CheckConstructorCall(FunctionDecl *FDecl,
- Expr **Args,
- unsigned NumArgs,
- const FunctionProtoType *Proto,
- SourceLocation Loc);
-
- void checkCall(NamedDecl *FDecl, Expr **Args, unsigned NumArgs,
- unsigned NumProtoArgs, bool IsMemberFunction,
- SourceLocation Loc, SourceRange Range,
- VariadicCallType CallType);
-
+ bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall);
bool CheckObjCString(Expr *Arg);
@@ -7079,31 +7037,21 @@
FST_Unknown
};
static FormatStringType GetFormatStringType(const FormatAttr *Format);
-
- enum StringLiteralCheckType {
- SLCT_NotALiteral,
- SLCT_UncheckedLiteral,
- SLCT_CheckedLiteral
- };
-
- StringLiteralCheckType checkFormatStringExpr(const Expr *E,
- Expr **Args, unsigned NumArgs,
- bool HasVAListArg,
- unsigned format_idx,
- unsigned firstDataArg,
- FormatStringType Type,
- bool inFunctionCall = true);
+ bool SemaCheckStringLiteral(const Expr *E, Expr **Args, unsigned NumArgs,
+ bool HasVAListArg, unsigned format_idx,
+ unsigned firstDataArg, FormatStringType Type,
+ bool inFunctionCall = true);
void CheckFormatString(const StringLiteral *FExpr, const Expr *OrigFormatExpr,
Expr **Args, unsigned NumArgs, bool HasVAListArg,
unsigned format_idx, unsigned firstDataArg,
FormatStringType Type, bool inFunctionCall);
- bool CheckFormatArguments(const FormatAttr *Format, CallExpr *TheCall);
- bool CheckFormatArguments(const FormatAttr *Format, Expr **Args,
+ void CheckFormatArguments(const FormatAttr *Format, CallExpr *TheCall);
+ void CheckFormatArguments(const FormatAttr *Format, Expr **Args,
unsigned NumArgs, bool IsCXXMember,
SourceLocation Loc, SourceRange Range);
- bool CheckFormatArguments(Expr **Args, unsigned NumArgs,
+ void CheckFormatArguments(Expr **Args, unsigned NumArgs,
bool HasVAListArg, unsigned format_idx,
unsigned firstDataArg, FormatStringType Type,
SourceLocation Loc, SourceRange range);
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=158949&r1=158948&r2=158949&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Thu Jun 21 18:44:21 2012
@@ -16,7 +16,6 @@
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Initialization.h"
-#include "clang/Sema/Lookup.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Analysis/Analyses/FormatString.h"
#include "clang/AST/ASTContext.h"
@@ -419,91 +418,34 @@
return false;
}
-/// Given a FunctionDecl's FormatAttr, attempts to populate the FomatStringInfo
-/// parameter with the FormatAttr's correct format_idx and firstDataArg.
-/// Returns true when the format fits the function and the FormatStringInfo has
-/// been populated.
-bool Sema::getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
- FormatStringInfo *FSI) {
- FSI->HasVAListArg = Format->getFirstArg() == 0;
- FSI->FormatIdx = Format->getFormatIdx() - 1;
- FSI->FirstDataArg = FSI->HasVAListArg ? 0 : Format->getFirstArg() - 1;
+/// CheckFunctionCall - Check a direct function call for various correctness
+/// and safety properties not strictly enforced by the C type system.
+bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
+ // Get the IdentifierInfo* for the called function.
+ IdentifierInfo *FnInfo = FDecl->getIdentifier();
- // The way the format attribute works in GCC, the implicit this argument
- // of member functions is counted. However, it doesn't appear in our own
- // lists, so decrement format_idx in that case.
- if (IsCXXMember) {
- if(FSI->FormatIdx == 0)
- return false;
- --FSI->FormatIdx;
- if (FSI->FirstDataArg != 0)
- --FSI->FirstDataArg;
- }
- return true;
-}
+ // None of the checks below are needed for functions that don't have
+ // simple names (e.g., C++ conversion functions).
+ if (!FnInfo)
+ return false;
-/// Handles the checks for format strings, non-POD arguments to vararg
-/// functions, and NULL arguments passed to non-NULL parameters.
-void Sema::checkCall(NamedDecl *FDecl, Expr **Args,
- unsigned NumArgs,
- unsigned NumProtoArgs,
- bool IsMemberFunction,
- SourceLocation Loc,
- SourceRange Range,
- VariadicCallType CallType) {
// FIXME: This mechanism should be abstracted to be less fragile and
// more efficient. For example, just map function ids to custom
// handlers.
// Printf and scanf checking.
- bool HandledFormatString = false;
for (specific_attr_iterator<FormatAttr>
- I = FDecl->specific_attr_begin<FormatAttr>(),
- E = FDecl->specific_attr_end<FormatAttr>(); I != E ; ++I)
- if (CheckFormatArguments(*I, Args, NumArgs, IsMemberFunction, Loc, Range))
- HandledFormatString = true;
-
- // Refuse POD arguments that weren't caught by the format string
- // checks above.
- if (!HandledFormatString && CallType != VariadicDoesNotApply)
- for (unsigned ArgIdx = NumProtoArgs; ArgIdx < NumArgs; ++ArgIdx)
- variadicArgumentPODCheck(Args[ArgIdx], CallType);
+ i = FDecl->specific_attr_begin<FormatAttr>(),
+ e = FDecl->specific_attr_end<FormatAttr>(); i != e ; ++i) {
+ CheckFormatArguments(*i, TheCall);
+ }
for (specific_attr_iterator<NonNullAttr>
- I = FDecl->specific_attr_begin<NonNullAttr>(),
- E = FDecl->specific_attr_end<NonNullAttr>(); I != E; ++I)
- CheckNonNullArguments(*I, Args, Loc);
-}
-
-/// CheckConstructorCall - Check a constructor call for correctness and safety
-/// properties not enforced by the C type system.
-void Sema::CheckConstructorCall(FunctionDecl *FDecl, Expr **Args,
- unsigned NumArgs,
- const FunctionProtoType *Proto,
- SourceLocation Loc) {
- VariadicCallType CallType =
- Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply;
- checkCall(FDecl, Args, NumArgs, Proto->getNumArgs(),
- /*IsMemberFunction=*/true, Loc, SourceRange(), CallType);
-}
-
-/// CheckFunctionCall - Check a direct function call for various correctness
-/// and safety properties not strictly enforced by the C type system.
-bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
- const FunctionProtoType *Proto) {
- bool IsMemberFunction = isa<CXXMemberCallExpr>(TheCall);
- VariadicCallType CallType = getVariadicCallType(FDecl, Proto,
- TheCall->getCallee());
- unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0;
- checkCall(FDecl, TheCall->getArgs(), TheCall->getNumArgs(), NumProtoArgs,
- IsMemberFunction, TheCall->getRParenLoc(),
- TheCall->getCallee()->getSourceRange(), CallType);
-
- IdentifierInfo *FnInfo = FDecl->getIdentifier();
- // None of the checks below are needed for functions that don't have
- // simple names (e.g., C++ conversion functions).
- if (!FnInfo)
- return false;
+ i = FDecl->specific_attr_begin<NonNullAttr>(),
+ e = FDecl->specific_attr_end<NonNullAttr>(); i != e; ++i) {
+ CheckNonNullArguments(*i, TheCall->getArgs(),
+ TheCall->getCallee()->getLocStart());
+ }
unsigned CMId = FDecl->getMemoryFunctionKind();
if (CMId == 0)
@@ -522,18 +464,25 @@
bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac,
Expr **Args, unsigned NumArgs) {
- VariadicCallType CallType =
- Method->isVariadic() ? VariadicMethod : VariadicDoesNotApply;
+ for (specific_attr_iterator<FormatAttr>
+ i = Method->specific_attr_begin<FormatAttr>(),
+ e = Method->specific_attr_end<FormatAttr>(); i != e ; ++i) {
+
+ CheckFormatArguments(*i, Args, NumArgs, false, lbrac,
+ Method->getSourceRange());
+ }
- checkCall(Method, Args, NumArgs, Method->param_size(),
- /*IsMemberFunction=*/false,
- lbrac, Method->getSourceRange(), CallType);
+ // diagnose nonnull arguments.
+ for (specific_attr_iterator<NonNullAttr>
+ i = Method->specific_attr_begin<NonNullAttr>(),
+ e = Method->specific_attr_end<NonNullAttr>(); i != e; ++i) {
+ CheckNonNullArguments(*i, Args, lbrac);
+ }
return false;
}
-bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall,
- const FunctionProtoType *Proto) {
+bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) {
const VarDecl *V = dyn_cast<VarDecl>(NDecl);
if (!V)
return false;
@@ -542,15 +491,13 @@
if (!Ty->isBlockPointerType())
return false;
- VariadicCallType CallType =
- Proto && Proto->isVariadic() ? VariadicBlock : VariadicDoesNotApply ;
- unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0;
-
- checkCall(NDecl, TheCall->getArgs(), TheCall->getNumArgs(),
- NumProtoArgs, /*IsMemberFunction=*/false,
- TheCall->getRParenLoc(),
- TheCall->getCallee()->getSourceRange(), CallType);
-
+ // format string checking.
+ for (specific_attr_iterator<FormatAttr>
+ i = NDecl->specific_attr_begin<FormatAttr>(),
+ e = NDecl->specific_attr_end<FormatAttr>(); i != e ; ++i) {
+ CheckFormatArguments(*i, TheCall);
+ }
+
return false;
}
@@ -1554,18 +1501,14 @@
return false;
}
-// Determine if an expression is a string literal or constant string.
-// If this function returns false on the arguments to a function expecting a
-// format string, we will usually need to emit a warning.
-// True string literals are then checked by CheckFormatString.
-Sema::StringLiteralCheckType
-Sema::checkFormatStringExpr(const Expr *E, Expr **Args,
- unsigned NumArgs, bool HasVAListArg,
- unsigned format_idx, unsigned firstDataArg,
- FormatStringType Type, bool inFunctionCall) {
+// Handle i > 1 ? "x" : "y", recursively.
+bool Sema::SemaCheckStringLiteral(const Expr *E, Expr **Args,
+ unsigned NumArgs, bool HasVAListArg,
+ unsigned format_idx, unsigned firstDataArg,
+ FormatStringType Type, bool inFunctionCall) {
tryAgain:
if (E->isTypeDependent() || E->isValueDependent())
- return SLCT_NotALiteral;
+ return false;
E = E->IgnoreParenCasts();
@@ -1574,26 +1517,18 @@
// The behavior of printf and friends in this case is implementation
// dependent. Ideally if the format string cannot be null then
// it should have a 'nonnull' attribute in the function prototype.
- return SLCT_CheckedLiteral;
+ return true;
switch (E->getStmtClass()) {
case Stmt::BinaryConditionalOperatorClass:
case Stmt::ConditionalOperatorClass: {
- // The expression is a literal if both sub-expressions were, and it was
- // completely checked only if both sub-expressions were checked.
- const AbstractConditionalOperator *C =
- cast<AbstractConditionalOperator>(E);
- StringLiteralCheckType Left =
- checkFormatStringExpr(C->getTrueExpr(), Args, NumArgs,
- HasVAListArg, format_idx, firstDataArg,
- Type, inFunctionCall);
- if (Left == SLCT_NotALiteral)
- return SLCT_NotALiteral;
- StringLiteralCheckType Right =
- checkFormatStringExpr(C->getFalseExpr(), Args, NumArgs,
- HasVAListArg, format_idx, firstDataArg,
- Type, inFunctionCall);
- return Left < Right ? Left : Right;
+ const AbstractConditionalOperator *C = cast<AbstractConditionalOperator>(E);
+ return SemaCheckStringLiteral(C->getTrueExpr(), Args, NumArgs, HasVAListArg,
+ format_idx, firstDataArg, Type,
+ inFunctionCall)
+ && SemaCheckStringLiteral(C->getFalseExpr(), Args, NumArgs, HasVAListArg,
+ format_idx, firstDataArg, Type,
+ inFunctionCall);
}
case Stmt::ImplicitCastExprClass: {
@@ -1606,13 +1541,13 @@
E = src;
goto tryAgain;
}
- return SLCT_NotALiteral;
+ return false;
case Stmt::PredefinedExprClass:
// While __func__, etc., are technically not string literals, they
// cannot contain format specifiers and thus are not a security
// liability.
- return SLCT_UncheckedLiteral;
+ return true;
case Stmt::DeclRefExprClass: {
const DeclRefExpr *DR = cast<DeclRefExpr>(E);
@@ -1641,10 +1576,9 @@
if (InitList->isStringLiteralInit())
Init = InitList->getInit(0)->IgnoreParenImpCasts();
}
- return checkFormatStringExpr(Init, Args, NumArgs,
- HasVAListArg, format_idx,
- firstDataArg, Type,
- /*inFunctionCall*/false);
+ return SemaCheckStringLiteral(Init, Args, NumArgs,
+ HasVAListArg, format_idx, firstDataArg,
+ Type, /*inFunctionCall*/false);
}
}
@@ -1678,14 +1612,14 @@
// We can't pass a 'scanf' string to a 'printf' function.
if (PVIndex == PVFormat->getFormatIdx() &&
Type == GetFormatStringType(PVFormat))
- return SLCT_UncheckedLiteral;
+ return true;
}
}
}
}
}
- return SLCT_NotALiteral;
+ return false;
}
case Stmt::CallExprClass:
@@ -1699,22 +1633,22 @@
--ArgIndex;
const Expr *Arg = CE->getArg(ArgIndex - 1);
- return checkFormatStringExpr(Arg, Args, NumArgs,
- HasVAListArg, format_idx, firstDataArg,
- Type, inFunctionCall);
+ return SemaCheckStringLiteral(Arg, Args, NumArgs, HasVAListArg,
+ format_idx, firstDataArg, Type,
+ inFunctionCall);
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
unsigned BuiltinID = FD->getBuiltinID();
if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString ||
BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString) {
const Expr *Arg = CE->getArg(0);
- return checkFormatStringExpr(Arg, Args, NumArgs,
- HasVAListArg, format_idx,
- firstDataArg, Type, inFunctionCall);
+ return SemaCheckStringLiteral(Arg, Args, NumArgs, HasVAListArg,
+ format_idx, firstDataArg, Type,
+ inFunctionCall);
}
}
}
- return SLCT_NotALiteral;
+ return false;
}
case Stmt::ObjCStringLiteralClass:
case Stmt::StringLiteralClass: {
@@ -1728,14 +1662,14 @@
if (StrE) {
CheckFormatString(StrE, E, Args, NumArgs, HasVAListArg, format_idx,
firstDataArg, Type, inFunctionCall);
- return SLCT_CheckedLiteral;
+ return true;
}
- return SLCT_NotALiteral;
+ return false;
}
default:
- return SLCT_NotALiteral;
+ return false;
}
}
@@ -1766,34 +1700,42 @@
/// CheckPrintfScanfArguments - Check calls to printf and scanf (and similar
/// functions) for correct use of format strings.
-/// Returns true if a format string has been fully checked.
-bool Sema::CheckFormatArguments(const FormatAttr *Format, CallExpr *TheCall) {
- bool IsCXXMember = isa<CXXMemberCallExpr>(TheCall);
- return CheckFormatArguments(Format, TheCall->getArgs(),
- TheCall->getNumArgs(),
- IsCXXMember, TheCall->getRParenLoc(),
- TheCall->getCallee()->getSourceRange());
+void Sema::CheckFormatArguments(const FormatAttr *Format, CallExpr *TheCall) {
+ bool IsCXXMember = false;
+ // The way the format attribute works in GCC, the implicit this argument
+ // of member functions is counted. However, it doesn't appear in our own
+ // lists, so decrement format_idx in that case.
+ IsCXXMember = isa<CXXMemberCallExpr>(TheCall);
+ CheckFormatArguments(Format, TheCall->getArgs(), TheCall->getNumArgs(),
+ IsCXXMember, TheCall->getRParenLoc(),
+ TheCall->getCallee()->getSourceRange());
}
-bool Sema::CheckFormatArguments(const FormatAttr *Format, Expr **Args,
+void Sema::CheckFormatArguments(const FormatAttr *Format, Expr **Args,
unsigned NumArgs, bool IsCXXMember,
SourceLocation Loc, SourceRange Range) {
- FormatStringInfo FSI;
- if (getFormatStringInfo(Format, IsCXXMember, &FSI))
- return CheckFormatArguments(Args, NumArgs, FSI.HasVAListArg, FSI.FormatIdx,
- FSI.FirstDataArg, GetFormatStringType(Format),
- Loc, Range);
- return false;
+ bool HasVAListArg = Format->getFirstArg() == 0;
+ unsigned format_idx = Format->getFormatIdx() - 1;
+ unsigned firstDataArg = HasVAListArg ? 0 : Format->getFirstArg() - 1;
+ if (IsCXXMember) {
+ if (format_idx == 0)
+ return;
+ --format_idx;
+ if(firstDataArg != 0)
+ --firstDataArg;
+ }
+ CheckFormatArguments(Args, NumArgs, HasVAListArg, format_idx,
+ firstDataArg, GetFormatStringType(Format), Loc, Range);
}
-bool Sema::CheckFormatArguments(Expr **Args, unsigned NumArgs,
+void Sema::CheckFormatArguments(Expr **Args, unsigned NumArgs,
bool HasVAListArg, unsigned format_idx,
unsigned firstDataArg, FormatStringType Type,
SourceLocation Loc, SourceRange Range) {
// CHECK: printf/scanf-like function is called with no format string.
if (format_idx >= NumArgs) {
Diag(Loc, diag::warn_missing_format_string) << Range;
- return false;
+ return;
}
const Expr *OrigFormatExpr = Args[format_idx]->IgnoreParenCasts();
@@ -1810,17 +1752,14 @@
// C string (e.g. "%d")
// ObjC string uses the same format specifiers as C string, so we can use
// the same format string checking logic for both ObjC and C strings.
- StringLiteralCheckType CT =
- checkFormatStringExpr(OrigFormatExpr, Args, NumArgs, HasVAListArg,
- format_idx, firstDataArg, Type);
- if (CT != SLCT_NotALiteral)
- // Literal format string found, check done!
- return CT == SLCT_CheckedLiteral;
+ if (SemaCheckStringLiteral(OrigFormatExpr, Args, NumArgs, HasVAListArg,
+ format_idx, firstDataArg, Type))
+ return; // Literal format string found, check done!
// Strftime is particular as it always uses a single 'time' argument,
// so it is safe to pass a non-literal string.
if (Type == FST_Strftime)
- return false;
+ return;
// Do not emit diag when the string param is a macro expansion and the
// format is either NSString or CFString. This is a hack to prevent
@@ -1828,7 +1767,7 @@
// which are usually used in place of NS and CF string literals.
if (Type == FST_NSString &&
SourceMgr.isInSystemMacro(Args[format_idx]->getLocStart()))
- return false;
+ return;
// If there are no arguments specified, warn with -Wformat-security, otherwise
// warn only with -Wformat-nonliteral.
@@ -1840,7 +1779,6 @@
Diag(Args[format_idx]->getLocStart(),
diag::warn_format_nonliteral)
<< OrigFormatExpr->getSourceRange();
- return false;
}
namespace {
@@ -2200,11 +2138,7 @@
bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
const char *startSpecifier,
unsigned specifierLen);
- bool checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
- const char *StartSpecifier,
- unsigned SpecifierLen,
- const Expr *E);
-
+
bool HandleAmount(const analyze_format_string::OptionalAmount &Amt, unsigned k,
const char *startSpecifier, unsigned specifierLen);
void HandleInvalidAmount(const analyze_printf::PrintfSpecifier &FS,
@@ -2218,9 +2152,6 @@
const analyze_printf::OptionalFlag &ignoredFlag,
const analyze_printf::OptionalFlag &flag,
const char *startSpecifier, unsigned specifierLen);
- bool checkForCStrMembers(const analyze_printf::ArgTypeResult &ATR,
- const Expr *E, const CharSourceRange &CSR);
-
};
}
@@ -2338,64 +2269,6 @@
getSpecifierRange(ignoredFlag.getPosition(), 1)));
}
-// Determines if the specified is a C++ class or struct containing
-// a member with the specified name and kind (e.g. a CXXMethodDecl named
-// "c_str()").
-template<typename MemberKind>
-static llvm::SmallPtrSet<MemberKind*, 1>
-CXXRecordMembersNamed(StringRef Name, Sema &S, QualType Ty) {
- const RecordType *RT = Ty->getAs<RecordType>();
- llvm::SmallPtrSet<MemberKind*, 1> Results;
-
- if (!RT)
- return Results;
- const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
- if (!RD)
- return Results;
-
- LookupResult R(S, &S.PP.getIdentifierTable().get(Name), SourceLocation(),
- Sema::LookupMemberName);
-
- // We just need to include all members of the right kind turned up by the
- // filter, at this point.
- if (S.LookupQualifiedName(R, RT->getDecl()))
- for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
- NamedDecl *decl = (*I)->getUnderlyingDecl();
- if (MemberKind *FK = dyn_cast<MemberKind>(decl))
- Results.insert(FK);
- }
- return Results;
-}
-
-// Check if a (w)string was passed when a (w)char* was needed, and offer a
-// better diagnostic if so. ATR is assumed to be valid.
-// Returns true when a c_str() conversion method is found.
-bool CheckPrintfHandler::checkForCStrMembers(
- const analyze_printf::ArgTypeResult &ATR, const Expr *E,
- const CharSourceRange &CSR) {
- typedef llvm::SmallPtrSet<CXXMethodDecl*, 1> MethodSet;
-
- MethodSet Results =
- CXXRecordMembersNamed<CXXMethodDecl>("c_str", S, E->getType());
-
- for (MethodSet::iterator MI = Results.begin(), ME = Results.end();
- MI != ME; ++MI) {
- const CXXMethodDecl *Method = *MI;
- if (Method->getNumParams() == 0 &&
- ATR.matchesType(S.Context, Method->getResultType())) {
- // FIXME: Suggest parens if the expression needs them.
- SourceLocation EndLoc =
- S.getPreprocessor().getLocForEndOfToken(E->getLocEnd());
- S.Diag(E->getLocStart(), diag::note_printf_c_str)
- << "c_str()"
- << FixItHint::CreateInsertion(EndLoc, ".c_str()");
- return true;
- }
- }
-
- return false;
-}
-
bool
CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier
&FS,
@@ -2523,30 +2396,20 @@
if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex))
return false;
- return checkFormatExpr(FS, startSpecifier, specifierLen,
- getDataArg(argIndex));
-}
-
-bool
-CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
- const char *StartSpecifier,
- unsigned SpecifierLen,
- const Expr *E) {
- using namespace analyze_format_string;
- using namespace analyze_printf;
// Now type check the data expression that matches the
// format specifier.
+ const Expr *Ex = getDataArg(argIndex);
const analyze_printf::ArgTypeResult &ATR = FS.getArgType(S.Context,
ObjCContext);
- if (ATR.isValid() && !ATR.matchesType(S.Context, E->getType())) {
+ if (ATR.isValid() && !ATR.matchesType(S.Context, Ex->getType())) {
// Look through argument promotions for our error message's reported type.
// This includes the integral and floating promotions, but excludes array
// and function pointer decay; seeing that an argument intended to be a
// string has type 'char [6]' is probably more confusing than 'char *'.
- if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+ if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Ex)) {
if (ICE->getCastKind() == CK_IntegralCast ||
ICE->getCastKind() == CK_FloatingCast) {
- E = ICE->getSubExpr();
+ Ex = ICE->getSubExpr();
// Check if we didn't match because of an implicit cast from a 'char'
// or 'short' to an 'int'. This is done because printf is a varargs
@@ -2554,7 +2417,7 @@
if (ICE->getType() == S.Context.IntTy ||
ICE->getType() == S.Context.UnsignedIntTy) {
// All further checking is done on the subexpression.
- if (ATR.matchesType(S.Context, E->getType()))
+ if (ATR.matchesType(S.Context, Ex->getType()))
return true;
}
}
@@ -2562,7 +2425,7 @@
// We may be able to offer a FixItHint if it is a supported type.
PrintfSpecifier fixedFS = FS;
- bool success = fixedFS.fixType(E->getType(), S.getLangOpts(),
+ bool success = fixedFS.fixType(Ex->getType(), S.getLangOpts(),
S.Context, ObjCContext);
if (success) {
@@ -2573,38 +2436,24 @@
EmitFormatDiagnostic(
S.PDiag(diag::warn_printf_conversion_argument_type_mismatch)
- << ATR.getRepresentativeTypeName(S.Context) << E->getType()
- << E->getSourceRange(),
- E->getLocStart(),
+ << ATR.getRepresentativeTypeName(S.Context) << Ex->getType()
+ << Ex->getSourceRange(),
+ Ex->getLocStart(),
/*IsStringLocation*/false,
- getSpecifierRange(StartSpecifier, SpecifierLen),
+ getSpecifierRange(startSpecifier, specifierLen),
FixItHint::CreateReplacement(
- getSpecifierRange(StartSpecifier, SpecifierLen),
+ getSpecifierRange(startSpecifier, specifierLen),
os.str()));
- } else {
- const CharSourceRange &CSR = getSpecifierRange(StartSpecifier,
- SpecifierLen);
- // Since the warning for passing non-POD types to variadic functions
- // was deferred until now, we emit a warning for non-POD
- // arguments here.
- if (S.isValidVarArgType(E->getType()) == Sema::VAK_Invalid) {
- EmitFormatDiagnostic(
- S.PDiag(diag::warn_non_pod_vararg_with_format_string)
- << S.getLangOpts().CPlusPlus0x
- << E->getType()
- << ATR.getRepresentativeTypeName(S.Context)
- << CSR
- << E->getSourceRange(),
- E->getLocStart(), /*IsStringLocation*/false, CSR);
-
- checkForCStrMembers(ATR, E, CSR);
- } else
- EmitFormatDiagnostic(
- S.PDiag(diag::warn_printf_conversion_argument_type_mismatch)
- << ATR.getRepresentativeTypeName(S.Context) << E->getType()
- << CSR
- << E->getSourceRange(),
- E->getLocStart(), /*IsStringLocation*/false, CSR);
+ }
+ else {
+ EmitFormatDiagnostic(
+ S.PDiag(diag::warn_printf_conversion_argument_type_mismatch)
+ << ATR.getRepresentativeTypeName(S.Context) << Ex->getType()
+ << getSpecifierRange(startSpecifier, specifierLen)
+ << Ex->getSourceRange(),
+ Ex->getLocStart(),
+ /*IsStringLocation*/false,
+ getSpecifierRange(startSpecifier, specifierLen));
}
}
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=158949&r1=158948&r2=158949&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Jun 21 18:44:21 2012
@@ -9028,6 +9028,13 @@
unsigned NumExprs = ExprArgs.size();
Expr **Exprs = (Expr **)ExprArgs.release();
+ for (specific_attr_iterator<NonNullAttr>
+ i = Constructor->specific_attr_begin<NonNullAttr>(),
+ e = Constructor->specific_attr_end<NonNullAttr>(); i != e; ++i) {
+ const NonNullAttr *NonNull = *i;
+ CheckNonNullArguments(NonNull, ExprArgs.get(), ConstructLoc);
+ }
+
MarkFunctionReferenced(ConstructLoc, Constructor);
return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc,
Constructor, Elidable, Exprs, NumExprs,
@@ -9093,7 +9100,7 @@
bool
Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
MultiExprArg ArgsPtr,
- SourceLocation Loc,
+ SourceLocation Loc,
ASTOwningVector<Expr*> &ConvertedArgs,
bool AllowExplicit) {
// FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall.
@@ -9121,8 +9128,7 @@
DiagnoseSentinelCalls(Constructor, Loc, AllArgs.data(), AllArgs.size());
- CheckConstructorCall(Constructor, AllArgs.data(), AllArgs.size(),
- Proto, Loc);
+ // FIXME: Missing call to CheckFunctionCall or equivalent
return Invalid;
}
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=158949&r1=158948&r2=158949&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Jun 21 18:44:21 2012
@@ -598,59 +598,12 @@
return Owned(E);
}
-/// Determine the degree of POD-ness for an expression.
-/// Incomplete types are considered POD, since this check can be performed
-/// when we're in an unevaluated context.
-Sema::VarArgKind Sema::isValidVarArgType(const QualType &Ty) {
- if (Ty->isIncompleteType() || Ty.isCXX98PODType(Context))
- return VAK_Valid;
- // C++0x [expr.call]p7:
- // Passing a potentially-evaluated argument of class type (Clause 9)
- // having a non-trivial copy constructor, a non-trivial move constructor,
- // or a non-trivial destructor, with no corresponding parameter,
- // is conditionally-supported with implementation-defined semantics.
-
- if (getLangOpts().CPlusPlus0x && !Ty->isDependentType())
- if (CXXRecordDecl *Record = Ty->getAsCXXRecordDecl())
- if (Record->hasTrivialCopyConstructor() &&
- Record->hasTrivialMoveConstructor() &&
- Record->hasTrivialDestructor())
- return VAK_ValidInCXX11;
-
- if (getLangOpts().ObjCAutoRefCount && Ty->isObjCLifetimeType())
- return VAK_Valid;
- return VAK_Invalid;
-}
-
-bool Sema::variadicArgumentPODCheck(const Expr *E, VariadicCallType CT) {
- // Don't allow one to pass an Objective-C interface to a vararg.
- const QualType & Ty = E->getType();
-
- // Complain about passing non-POD types through varargs.
- switch (isValidVarArgType(Ty)) {
- case VAK_Valid:
- break;
- case VAK_ValidInCXX11:
- DiagRuntimeBehavior(E->getLocStart(), 0,
- PDiag(diag::warn_cxx98_compat_pass_non_pod_arg_to_vararg)
- << E->getType() << CT);
- break;
- case VAK_Invalid:
- return DiagRuntimeBehavior(E->getLocStart(), 0,
- PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
- << getLangOpts().CPlusPlus0x << Ty << CT);
- }
- // c++ rules are enforced elsewhere.
- return false;
-}
-
/// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
/// will warn if the resulting type is not a POD type, and rejects ObjC
/// interfaces passed by value.
ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
FunctionDecl *FDecl) {
- const QualType &Ty = E->getType();
- if (const BuiltinType *PlaceholderTy = Ty->getAsPlaceholderType()) {
+ if (const BuiltinType *PlaceholderTy = E->getType()->getAsPlaceholderType()) {
// Strip the unbridged-cast placeholder expression off, if applicable.
if (PlaceholderTy->getKind() == BuiltinType::ARCUnbridgedCast &&
(CT == VariadicMethod ||
@@ -671,44 +624,77 @@
return ExprError();
E = ExprRes.take();
- if (Ty->isObjCObjectType() &&
+ // Don't allow one to pass an Objective-C interface to a vararg.
+ if (E->getType()->isObjCObjectType() &&
DiagRuntimeBehavior(E->getLocStart(), 0,
PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
- << Ty << CT))
+ << E->getType() << CT))
return ExprError();
- // Diagnostics regarding non-POD argument types are
- // emitted along with format string checking in Sema::CheckFunctionCall().
- if (isValidVarArgType(Ty) == VAK_Invalid) {
- // Turn this into a trap.
- CXXScopeSpec SS;
- SourceLocation TemplateKWLoc;
- UnqualifiedId Name;
- Name.setIdentifier(PP.getIdentifierInfo("__builtin_trap"),
- E->getLocStart());
- ExprResult TrapFn = ActOnIdExpression(TUScope, SS, TemplateKWLoc,
- Name, true, false);
- if (TrapFn.isInvalid())
- return ExprError();
+ // Complain about passing non-POD types through varargs. However, don't
+ // perform this check for incomplete types, which we can get here when we're
+ // in an unevaluated context.
+ if (!E->getType()->isIncompleteType() &&
+ !E->getType().isCXX98PODType(Context)) {
+ // C++0x [expr.call]p7:
+ // Passing a potentially-evaluated argument of class type (Clause 9)
+ // having a non-trivial copy constructor, a non-trivial move constructor,
+ // or a non-trivial destructor, with no corresponding parameter,
+ // is conditionally-supported with implementation-defined semantics.
+ bool TrivialEnough = false;
+ if (getLangOpts().CPlusPlus0x && !E->getType()->isDependentType()) {
+ if (CXXRecordDecl *Record = E->getType()->getAsCXXRecordDecl()) {
+ if (Record->hasTrivialCopyConstructor() &&
+ Record->hasTrivialMoveConstructor() &&
+ Record->hasTrivialDestructor()) {
+ DiagRuntimeBehavior(E->getLocStart(), 0,
+ PDiag(diag::warn_cxx98_compat_pass_non_pod_arg_to_vararg)
+ << E->getType() << CT);
+ TrivialEnough = true;
+ }
+ }
+ }
- ExprResult Call = ActOnCallExpr(TUScope, TrapFn.get(),
- E->getLocStart(), MultiExprArg(),
- E->getLocEnd());
- if (Call.isInvalid())
- return ExprError();
+ if (!TrivialEnough &&
+ getLangOpts().ObjCAutoRefCount &&
+ E->getType()->isObjCLifetimeType())
+ TrivialEnough = true;
+
+ if (TrivialEnough) {
+ // Nothing to diagnose. This is okay.
+ } else if (DiagRuntimeBehavior(E->getLocStart(), 0,
+ PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
+ << getLangOpts().CPlusPlus0x << E->getType()
+ << CT)) {
+ // Turn this into a trap.
+ CXXScopeSpec SS;
+ SourceLocation TemplateKWLoc;
+ UnqualifiedId Name;
+ Name.setIdentifier(PP.getIdentifierInfo("__builtin_trap"),
+ E->getLocStart());
+ ExprResult TrapFn = ActOnIdExpression(TUScope, SS, TemplateKWLoc, Name,
+ true, false);
+ if (TrapFn.isInvalid())
+ return ExprError();
- ExprResult Comma = ActOnBinOp(TUScope, E->getLocStart(), tok::comma,
- Call.get(), E);
- if (Comma.isInvalid())
- return ExprError();
- return Comma.get();
+ ExprResult Call = ActOnCallExpr(TUScope, TrapFn.get(), E->getLocStart(),
+ MultiExprArg(), E->getLocEnd());
+ if (Call.isInvalid())
+ return ExprError();
+
+ ExprResult Comma = ActOnBinOp(TUScope, E->getLocStart(), tok::comma,
+ Call.get(), E);
+ if (Comma.isInvalid())
+ return ExprError();
+ E = Comma.get();
+ }
}
-
+ // c++ rules are enforced elsewhere.
if (!getLangOpts().CPlusPlus &&
RequireCompleteType(E->getExprLoc(), E->getType(),
diag::err_call_incomplete_argument))
return ExprError();
-
+
return Owned(E);
}
@@ -3437,25 +3423,6 @@
return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param));
}
-
-Sema::VariadicCallType
-Sema::getVariadicCallType(FunctionDecl *FDecl, const FunctionProtoType *Proto,
- Expr *Fn) {
- if (Proto && Proto->isVariadic()) {
- if (dyn_cast_or_null<CXXConstructorDecl>(FDecl))
- return VariadicConstructor;
- else if (Fn && Fn->getType()->isBlockPointerType())
- return VariadicBlock;
- else if (FDecl) {
- if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(FDecl))
- if (Method->isInstance())
- return VariadicMethod;
- return VariadicFunction;
- }
- }
- return VariadicDoesNotApply;
-}
-
/// ConvertArgumentsForCall - Converts the arguments specified in
/// Args/NumArgs to the parameter types of the function FDecl with
/// function prototype Proto. Call is the call expression itself, and
@@ -3547,8 +3514,12 @@
}
}
SmallVector<Expr *, 8> AllArgs;
- VariadicCallType CallType = getVariadicCallType(FDecl, Proto, Fn);
-
+ VariadicCallType CallType =
+ Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply;
+ if (Fn->getType()->isBlockPointerType())
+ CallType = VariadicBlock; // Block
+ else if (isa<MemberExpr>(Fn))
+ CallType = VariadicMethod;
Invalid = GatherArgumentsForCall(Call->getLocStart(), FDecl,
Proto, 0, Args, NumArgs, AllArgs, CallType);
if (Invalid)
@@ -3637,6 +3608,7 @@
// If this is a variadic call, handle args passed through "...".
if (CallType != VariadicDoesNotApply) {
+
// Assume that extern "C" functions with variadic arguments that
// return __unknown_anytype aren't *really* variadic.
if (Proto->getResultType() == Context.UnknownAnyTy &&
@@ -3974,8 +3946,7 @@
TheCall->setType(FuncT->getCallResultType(Context));
TheCall->setValueKind(Expr::getValueKindForType(FuncT->getResultType()));
- const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT);
- if (Proto) {
+ if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT)) {
if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, NumArgs,
RParenLoc, IsExecConfig))
return ExprError();
@@ -3987,7 +3958,8 @@
// on our knowledge of the function definition.
const FunctionDecl *Def = 0;
if (FDecl->hasBody(Def) && NumArgs != Def->param_size()) {
- Proto = Def->getType()->getAs<FunctionProtoType>();
+ const FunctionProtoType *Proto
+ = Def->getType()->getAs<FunctionProtoType>();
if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size()))
Diag(RParenLoc, diag::warn_call_wrong_number_of_arguments)
<< (NumArgs > Def->param_size()) << FDecl << Fn->getSourceRange();
@@ -4045,13 +4017,13 @@
// Do special checking on direct calls to functions.
if (FDecl) {
- if (CheckFunctionCall(FDecl, TheCall, Proto))
+ if (CheckFunctionCall(FDecl, TheCall))
return ExprError();
if (BuiltinID)
return CheckBuiltinFunctionCall(BuiltinID, TheCall);
} else if (NDecl) {
- if (CheckBlockCall(NDecl, TheCall, Proto))
+ if (CheckBlockCall(NDecl, TheCall))
return ExprError();
}
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=158949&r1=158948&r2=158949&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Jun 21 18:44:21 2012
@@ -10720,7 +10720,7 @@
DiagnoseSentinelCalls(Method, LParenLoc, Args, NumArgs);
- if (CheckFunctionCall(Method, TheCall, Proto))
+ if (CheckFunctionCall(Method, TheCall))
return ExprError();
if ((isa<CXXConstructorDecl>(CurContext) ||
@@ -11028,7 +11028,7 @@
DiagnoseSentinelCalls(Method, LParenLoc, Args, NumArgs);
- if (CheckFunctionCall(Method, TheCall, Proto))
+ if (CheckFunctionCall(Method, TheCall))
return true;
return MaybeBindToTemporary(TheCall);
@@ -11208,7 +11208,7 @@
if (CheckCallReturnType(FD->getResultType(), UDSuffixLoc, UDL, FD))
return ExprError();
- if (CheckFunctionCall(FD, UDL, NULL))
+ if (CheckFunctionCall(FD, UDL))
return ExprError();
return MaybeBindToTemporary(UDL);
Removed: cfe/trunk/test/SemaCXX/printf-block.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/printf-block.cpp?rev=158948&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/printf-block.cpp (original)
+++ cfe/trunk/test/SemaCXX/printf-block.cpp (removed)
@@ -1,18 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -fblocks -Wformat -verify %s -Wno-error=non-pod-varargs
-
-int (^block) (int, const char *,...) __attribute__((__format__(__printf__,2,3))) = ^ __attribute__((__format__(__printf__,2,3))) (int arg, const char *format,...) {return 5;};
-
-class HasNoCStr {
- const char *str;
- public:
- HasNoCStr(const char *s): str(s) { }
- const char *not_c_str() {return str;}
-};
-
-void test_block() {
- const char str[] = "test";
- HasNoCStr hncs(str);
- int n = 4;
- block(n, "%s %d", str, n); // no-warning
- block(n, "%s %s", hncs, n); // expected-warning{{cannot pass non-POD object of type 'HasNoCStr' to variadic function; expected type from format string was 'char *'}} expected-warning{{format specifies type 'char *' but the argument has type 'int'}}
-}
Removed: cfe/trunk/test/SemaCXX/printf-cstr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/printf-cstr.cpp?rev=158948&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/printf-cstr.cpp (original)
+++ cfe/trunk/test/SemaCXX/printf-cstr.cpp (removed)
@@ -1,53 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -Wformat -verify %s -Wno-error=non-pod-varargs
-
-#include <stdarg.h>
-
-extern "C" {
-extern int printf(const char *restrict, ...);
-extern int sprintf(char *, const char *restrict, ...);
-}
-
-class HasCStr {
- const char *str;
- public:
- HasCStr(const char *s): str(s) { }
- const char *c_str() {return str;}
-};
-
-class HasNoCStr {
- const char *str;
- public:
- HasNoCStr(const char *s): str(s) { }
- const char *not_c_str() {return str;}
-};
-
-extern const char extstr[16];
-void pod_test() {
- char str[] = "test";
- char dest[32];
- char formatString[] = "non-const %s %s";
- HasCStr hcs(str);
- HasNoCStr hncs(str);
- int n = 10;
-
- printf("%d: %s\n", n, hcs.c_str());
- printf("%d: %s\n", n, hcs); // expected-warning{{cannot pass non-POD object of type 'HasCStr' to variadic function; expected type from format string was 'char *'}} expected-note{{did you mean to call the c_str() method?}}
- printf("%d: %s\n", n, hncs); // expected-warning{{cannot pass non-POD object of type 'HasNoCStr' to variadic function; expected type from format string was 'char *'}}
- sprintf(str, "%d: %s", n, hcs); // expected-warning{{cannot pass non-POD object of type 'HasCStr' to variadic function; expected type from format string was 'char *'}} expected-note{{did you mean to call the c_str() method?}}
-
- printf(formatString, hcs, hncs); // expected-warning{{cannot pass object of non-POD type 'HasCStr' through variadic function}} expected-warning{{cannot pass object of non-POD type 'HasNoCStr' through variadic function}}
- printf(extstr, hcs, n); // expected-warning{{cannot pass object of non-POD type 'HasCStr' through variadic function}}
-}
-
-struct Printf {
- Printf();
- Printf(const Printf&);
- Printf(const char *,...) __attribute__((__format__(__printf__,2,3)));
-};
-
-void constructor_test() {
- const char str[] = "test";
- HasCStr hcs(str);
- Printf p("%s %d %s", str, 10, 10); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
- Printf q("%s %d", hcs, 10); // expected-warning {{cannot pass non-POD object of type 'HasCStr' to variadic function; expected type from format string was 'char *'}} expected-note{{did you mean to call the c_str() method?}}
-}
More information about the cfe-commits
mailing list