[cfe-commits] r159159 - 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/Sema
Richard Smith
richard at metafoo.co.uk
Wed Jun 27 13:31:50 PDT 2012
Thanks, this should be fixed in r159290.
On Wed, Jun 27, 2012 at 11:31 AM, David Dean <david_dean at apple.com> wrote:
> Some of the gcc test suite tests are failing after this commit.
>
> You should be able to reproduce with:
>
> gcc -m64 -DSKIP_DECIMAL_FLOAT -c -o c_compat_x_alt.o \
> clang-tests/gcc-4_2-testsuite/src/gcc.dg/compat/fnptr-by-value-1_x.c
> gcc -m64 -DSKIP_DECIMAL_FLOAT -c -o c_compat_y_alt.o \
> clang-tests/gcc-4_2-testsuite/src/gcc.dg/compat/fnptr-by-value-1_y.c
> clang -m64 -DSKIP_DECIMAL_FLOAT -c -o c_compat_main_tst.o \
> clang-tests/gcc-4_2-testsuite/src/gcc.dg/compat/fnptr-by-value-1_main.c
> clang -m64 -DSKIP_DECIMAL_FLOAT -c -o c_compat_x_tst.o \
> clang-tests/gcc-4_2-testsuite/src/gcc.dg/compat/fnptr-by-value-1_x.c
> clang -m64 -DSKIP_DECIMAL_FLOAT -c -o c_compat_y_tst.o \
> clang-tests/gcc-4_2-testsuite/src/gcc.dg/compat/fnptr-by-value-1_y.c
> clang c_compat_main_tst.o c_compat_x_tst.o c_compat_y_alt.o -m64 \
> -Wl,-multiply_defined,suppress -lm -o gcc-dg-compat-fnptr-by-value-1-02
> ./gcc-dg-compat-fnptr-by-value-1-02
>
>
> On 25 Jun 2012, at 1:30 PM, Richard Smith wrote:
>
> > Author: rsmith
> > Date: Mon Jun 25 15:30:08 2012
> > New Revision: 159159
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=159159&view=rev
> > Log:
> > Unrevert r158887, reverted in r158949, along with a fix for the bug which
> > resulted in it being reverted. A test for that bug was added in r158950.
> >
> > Original comment:
> >
> > If an object (such as a std::string) with an appropriate c_str() member
> function
> > is passed to a variadic function in a position where a format string
> indicates
> > that c_str()'s return type is desired, provide a note suggesting that
> the user
> > may have intended to call the c_str() member.
> >
> > Factor the non-POD-vararg checking out of
> DefaultVariadicArgumentPromotion and
> > move it to SemaChecking in order to facilitate this. Factor the call
> checking
> > out of function call checking and block call checking, and extend it to
> cover
> > constructor calls too.
> >
> > Patch by Sam Panzer!
> >
> > Added:
> > cfe/trunk/test/SemaCXX/printf-block.cpp
> > - copied unchanged from r158948,
> cfe/trunk/test/SemaCXX/printf-block.cpp
> > cfe/trunk/test/SemaCXX/printf-cstr.cpp
> > - copied unchanged from r158948,
> 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=159159&r1=159158&r2=159159&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> > +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Jun 25
> 15:30:08 2012
> > @@ -4725,6 +4725,11 @@
> > "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">,
> > @@ -5208,7 +5213,8 @@
> > "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>;
> > @@ -5675,4 +5681,3 @@
> > } // end of documentation issue category
> >
> > } // 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=159159&r1=159158&r2=159159&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Sema/Sema.h (original)
> > +++ cfe/trunk/include/clang/Sema/Sema.h Mon Jun 25 15:30:08 2012
> > @@ -6408,6 +6408,21 @@
> > 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,
> > @@ -6420,10 +6435,14 @@
> > bool AllowExplicit = false);
> >
> > // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion,
> but
> > - // will warn if the resulting type is not a POD type.
> > + // will return ExprError() 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
> > @@ -6998,10 +7017,33 @@
> > const ArraySubscriptExpr *ASE=0,
> > bool AllowOnePastEnd=true, bool
> IndexNegated=false);
> > void CheckArrayAccess(const Expr *E);
> > - bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall);
> > + // 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 CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc,
> > Expr **Args, unsigned NumArgs);
> > - bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall);
> > + 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 CheckObjCString(Expr *Arg);
> >
> > @@ -7036,21 +7078,31 @@
> > FST_Unknown
> > };
> > static FormatStringType GetFormatStringType(const FormatAttr *Format);
> > - bool SemaCheckStringLiteral(const Expr *E, Expr **Args, unsigned
> NumArgs,
> > - bool HasVAListArg, unsigned format_idx,
> > - unsigned firstDataArg, FormatStringType
> Type,
> > - bool inFunctionCall = true);
> > +
> > + 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);
> >
> > void CheckFormatString(const StringLiteral *FExpr, const Expr
> *OrigFormatExpr,
> > Expr **Args, unsigned NumArgs, bool
> HasVAListArg,
> > unsigned format_idx, unsigned firstDataArg,
> > FormatStringType Type, bool inFunctionCall);
> >
> > - void CheckFormatArguments(const FormatAttr *Format, CallExpr
> *TheCall);
> > - void CheckFormatArguments(const FormatAttr *Format, Expr **Args,
> > + bool CheckFormatArguments(const FormatAttr *Format, CallExpr
> *TheCall);
> > + bool CheckFormatArguments(const FormatAttr *Format, Expr **Args,
> > unsigned NumArgs, bool IsCXXMember,
> > SourceLocation Loc, SourceRange Range);
> > - void CheckFormatArguments(Expr **Args, unsigned NumArgs,
> > + bool 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=159159&r1=159158&r2=159159&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaChecking.cpp Mon Jun 25 15:30:08 2012
> > @@ -16,6 +16,7 @@
> > #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"
> > @@ -418,34 +419,91 @@
> > return false;
> > }
> >
> > -/// 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();
> > +/// 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;
> >
> > - // None of the checks below are needed for functions that don't have
> > - // simple names (e.g., C++ conversion functions).
> > - if (!FnInfo)
> > - return 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.
> > + if (IsCXXMember) {
> > + if(FSI->FormatIdx == 0)
> > + return false;
> > + --FSI->FormatIdx;
> > + if (FSI->FirstDataArg != 0)
> > + --FSI->FirstDataArg;
> > + }
> > + return true;
> > +}
> >
> > +/// 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) {
> > - CheckFormatArguments(*i, TheCall);
> > - }
> > + 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);
> >
> > for (specific_attr_iterator<NonNullAttr>
> > - i = FDecl->specific_attr_begin<NonNullAttr>(),
> > - e = FDecl->specific_attr_end<NonNullAttr>(); i != e; ++i) {
> > - CheckNonNullArguments(*i, TheCall->getArgs(),
> > - TheCall->getCallee()->getLocStart());
> > - }
> > + 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;
> >
> > unsigned CMId = FDecl->getMemoryFunctionKind();
> > if (CMId == 0)
> > @@ -464,25 +522,18 @@
> >
> > bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation
> lbrac,
> > Expr **Args, unsigned NumArgs) {
> > - 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());
> > - }
> > + VariadicCallType CallType =
> > + Method->isVariadic() ? VariadicMethod : VariadicDoesNotApply;
> >
> > - // 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);
> > - }
> > + checkCall(Method, Args, NumArgs, Method->param_size(),
> > + /*IsMemberFunction=*/false,
> > + lbrac, Method->getSourceRange(), CallType);
> >
> > return false;
> > }
> >
> > -bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) {
> > +bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall,
> > + const FunctionProtoType *Proto) {
> > const VarDecl *V = dyn_cast<VarDecl>(NDecl);
> > if (!V)
> > return false;
> > @@ -491,13 +542,15 @@
> > if (!Ty->isBlockPointerType())
> > return false;
> >
> > - // 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);
> > - }
> > -
> > + 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);
> > +
> > return false;
> > }
> >
> > @@ -1501,14 +1554,18 @@
> > return false;
> > }
> >
> > -// 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) {
> > +// 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)
> {
> > tryAgain:
> > if (E->isTypeDependent() || E->isValueDependent())
> > - return false;
> > + return SLCT_NotALiteral;
> >
> > E = E->IgnoreParenCasts();
> >
> > @@ -1517,18 +1574,26 @@
> > // 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 true;
> > + return SLCT_CheckedLiteral;
> >
> > switch (E->getStmtClass()) {
> > case Stmt::BinaryConditionalOperatorClass:
> > case Stmt::ConditionalOperatorClass: {
> > - 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);
> > + // 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;
> > }
> >
> > case Stmt::ImplicitCastExprClass: {
> > @@ -1541,13 +1606,13 @@
> > E = src;
> > goto tryAgain;
> > }
> > - return false;
> > + return SLCT_NotALiteral;
> >
> > case Stmt::PredefinedExprClass:
> > // While __func__, etc., are technically not string literals, they
> > // cannot contain format specifiers and thus are not a security
> > // liability.
> > - return true;
> > + return SLCT_UncheckedLiteral;
> >
> > case Stmt::DeclRefExprClass: {
> > const DeclRefExpr *DR = cast<DeclRefExpr>(E);
> > @@ -1576,9 +1641,10 @@
> > if (InitList->isStringLiteralInit())
> > Init = InitList->getInit(0)->IgnoreParenImpCasts();
> > }
> > - return SemaCheckStringLiteral(Init, Args, NumArgs,
> > - HasVAListArg, format_idx,
> firstDataArg,
> > - Type, /*inFunctionCall*/false);
> > + return checkFormatStringExpr(Init, Args, NumArgs,
> > + HasVAListArg, format_idx,
> > + firstDataArg, Type,
> > + /*inFunctionCall*/false);
> > }
> > }
> >
> > @@ -1612,14 +1678,14 @@
> > // We can't pass a 'scanf' string to a 'printf' function.
> > if (PVIndex == PVFormat->getFormatIdx() &&
> > Type == GetFormatStringType(PVFormat))
> > - return true;
> > + return SLCT_UncheckedLiteral;
> > }
> > }
> > }
> > }
> > }
> >
> > - return false;
> > + return SLCT_NotALiteral;
> > }
> >
> > case Stmt::CallExprClass:
> > @@ -1633,22 +1699,22 @@
> > --ArgIndex;
> > const Expr *Arg = CE->getArg(ArgIndex - 1);
> >
> > - return SemaCheckStringLiteral(Arg, Args, NumArgs, HasVAListArg,
> > - format_idx, firstDataArg, Type,
> > - inFunctionCall);
> > + return checkFormatStringExpr(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 SemaCheckStringLiteral(Arg, Args, NumArgs,
> HasVAListArg,
> > - format_idx, firstDataArg, Type,
> > - inFunctionCall);
> > + return checkFormatStringExpr(Arg, Args, NumArgs,
> > + HasVAListArg, format_idx,
> > + firstDataArg, Type,
> inFunctionCall);
> > }
> > }
> > }
> >
> > - return false;
> > + return SLCT_NotALiteral;
> > }
> > case Stmt::ObjCStringLiteralClass:
> > case Stmt::StringLiteralClass: {
> > @@ -1662,14 +1728,14 @@
> > if (StrE) {
> > CheckFormatString(StrE, E, Args, NumArgs, HasVAListArg, format_idx,
> > firstDataArg, Type, inFunctionCall);
> > - return true;
> > + return SLCT_CheckedLiteral;
> > }
> >
> > - return false;
> > + return SLCT_NotALiteral;
> > }
> >
> > default:
> > - return false;
> > + return SLCT_NotALiteral;
> > }
> > }
> >
> > @@ -1700,42 +1766,34 @@
> >
> > /// CheckPrintfScanfArguments - Check calls to printf and scanf (and
> similar
> > /// functions) for correct use of format strings.
> > -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());
> > +/// 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, Expr **Args,
> > +bool Sema::CheckFormatArguments(const FormatAttr *Format, Expr **Args,
> > unsigned NumArgs, bool IsCXXMember,
> > SourceLocation Loc, SourceRange Range) {
> > - 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);
> > + FormatStringInfo FSI;
> > + if (getFormatStringInfo(Format, IsCXXMember, &FSI))
> > + return CheckFormatArguments(Args, NumArgs, FSI.HasVAListArg,
> FSI.FormatIdx,
> > + FSI.FirstDataArg,
> GetFormatStringType(Format),
> > + Loc, Range);
> > + return false;
> > }
> >
> > -void Sema::CheckFormatArguments(Expr **Args, unsigned NumArgs,
> > +bool 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;
> > + return false;
> > }
> >
> > const Expr *OrigFormatExpr = Args[format_idx]->IgnoreParenCasts();
> > @@ -1752,14 +1810,17 @@
> > // 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.
> > - if (SemaCheckStringLiteral(OrigFormatExpr, Args, NumArgs,
> HasVAListArg,
> > - format_idx, firstDataArg, Type))
> > - return; // Literal format string found, check done!
> > + 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;
> >
> > // 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;
> > + return false;
> >
> > // 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
> > @@ -1767,7 +1828,7 @@
> > // which are usually used in place of NS and CF string literals.
> > if (Type == FST_NSString &&
> > SourceMgr.isInSystemMacro(Args[format_idx]->getLocStart()))
> > - return;
> > + return false;
> >
> > // If there are no arguments specified, warn with -Wformat-security,
> otherwise
> > // warn only with -Wformat-nonliteral.
> > @@ -1779,6 +1840,7 @@
> > Diag(Args[format_idx]->getLocStart(),
> > diag::warn_format_nonliteral)
> > << OrigFormatExpr->getSourceRange();
> > + return false;
> > }
> >
> > namespace {
> > @@ -2138,7 +2200,11 @@
> > 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,
> > @@ -2152,6 +2218,9 @@
> > 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);
> > +
> > };
> > }
> >
> > @@ -2269,6 +2338,64 @@
> > 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,
> > @@ -2396,20 +2523,30 @@
> > 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, Ex->getType())) {
> > + if (ATR.isValid() && !ATR.matchesType(S.Context, E->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>(Ex)) {
> > + if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
> > if (ICE->getCastKind() == CK_IntegralCast ||
> > ICE->getCastKind() == CK_FloatingCast) {
> > - Ex = ICE->getSubExpr();
> > + E = 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
> > @@ -2417,7 +2554,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, Ex->getType()))
> > + if (ATR.matchesType(S.Context, E->getType()))
> > return true;
> > }
> > }
> > @@ -2425,7 +2562,7 @@
> >
> > // We may be able to offer a FixItHint if it is a supported type.
> > PrintfSpecifier fixedFS = FS;
> > - bool success = fixedFS.fixType(Ex->getType(), S.getLangOpts(),
> > + bool success = fixedFS.fixType(E->getType(), S.getLangOpts(),
> > S.Context, ObjCContext);
> >
> > if (success) {
> > @@ -2436,24 +2573,38 @@
> >
> > EmitFormatDiagnostic(
> > S.PDiag(diag::warn_printf_conversion_argument_type_mismatch)
> > - << ATR.getRepresentativeTypeName(S.Context) << Ex->getType()
> > - << Ex->getSourceRange(),
> > - Ex->getLocStart(),
> > + << ATR.getRepresentativeTypeName(S.Context) << E->getType()
> > + << E->getSourceRange(),
> > + E->getLocStart(),
> > /*IsStringLocation*/false,
> > - getSpecifierRange(startSpecifier, specifierLen),
> > + getSpecifierRange(StartSpecifier, SpecifierLen),
> > FixItHint::CreateReplacement(
> > - getSpecifierRange(startSpecifier, specifierLen),
> > + getSpecifierRange(StartSpecifier, SpecifierLen),
> > os.str()));
> > - }
> > - 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));
> > + } 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);
> > }
> > }
> >
> >
> > Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=159159&r1=159158&r2=159159&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Jun 25 15:30:08 2012
> > @@ -9028,13 +9028,6 @@
> > 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,
> > @@ -9100,7 +9093,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.
> > @@ -9128,7 +9121,8 @@
> >
> > DiagnoseSentinelCalls(Constructor, Loc, AllArgs.data(),
> AllArgs.size());
> >
> > - // FIXME: Missing call to CheckFunctionCall or equivalent
> > + CheckConstructorCall(Constructor, AllArgs.data(), AllArgs.size(),
> > + Proto, Loc);
> >
> > return Invalid;
> > }
> >
> > Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=159159&r1=159158&r2=159159&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Jun 25 15:30:08 2012
> > @@ -598,12 +598,59 @@
> > 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) {
> > - if (const BuiltinType *PlaceholderTy =
> E->getType()->getAsPlaceholderType()) {
> > + const QualType &Ty = E->getType();
> > + if (const BuiltinType *PlaceholderTy = Ty->getAsPlaceholderType()) {
> > // Strip the unbridged-cast placeholder expression off, if
> applicable.
> > if (PlaceholderTy->getKind() == BuiltinType::ARCUnbridgedCast &&
> > (CT == VariadicMethod ||
> > @@ -624,77 +671,44 @@
> > return ExprError();
> > E = ExprRes.take();
> >
> > - // Don't allow one to pass an Objective-C interface to a vararg.
> > - if (E->getType()->isObjCObjectType() &&
> > + if (Ty->isObjCObjectType() &&
> > DiagRuntimeBehavior(E->getLocStart(), 0,
> >
> PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
> > - << E->getType() << CT))
> > + << Ty << CT))
> > 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;
> > - }
> > - }
> > - }
> > + // 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();
> >
> > - 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 Call = ActOnCallExpr(TUScope, TrapFn.get(),
> > + E->getLocStart(), MultiExprArg(),
> > + E->getLocEnd());
> > + if (Call.isInvalid())
> > + return ExprError();
> >
> > - 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();
> > - }
> > + ExprResult Comma = ActOnBinOp(TUScope, E->getLocStart(), tok::comma,
> > + Call.get(), E);
> > + if (Comma.isInvalid())
> > + return ExprError();
> > + return 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);
> > }
> >
> > @@ -3431,6 +3445,25 @@
> > 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
> > @@ -3522,12 +3555,8 @@
> > }
> > }
> > SmallVector<Expr *, 8> AllArgs;
> > - VariadicCallType CallType =
> > - Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply;
> > - if (Fn->getType()->isBlockPointerType())
> > - CallType = VariadicBlock; // Block
> > - else if (isa<MemberExpr>(Fn))
> > - CallType = VariadicMethod;
> > + VariadicCallType CallType = getVariadicCallType(FDecl, Proto, Fn);
> > +
> > Invalid = GatherArgumentsForCall(Call->getLocStart(), FDecl,
> > Proto, 0, Args, NumArgs, AllArgs,
> CallType);
> > if (Invalid)
> > @@ -3616,7 +3645,6 @@
> >
> > // 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 &&
> > @@ -3954,7 +3982,8 @@
> > TheCall->setType(FuncT->getCallResultType(Context));
> >
> TheCall->setValueKind(Expr::getValueKindForType(FuncT->getResultType()));
> >
> > - if (const FunctionProtoType *Proto =
> dyn_cast<FunctionProtoType>(FuncT)) {
> > + const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT);
> > + if (Proto) {
> > if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, NumArgs,
> > RParenLoc, IsExecConfig))
> > return ExprError();
> > @@ -3966,8 +3995,7 @@
> > // on our knowledge of the function definition.
> > const FunctionDecl *Def = 0;
> > if (FDecl->hasBody(Def) && NumArgs != Def->param_size()) {
> > - const FunctionProtoType *Proto
> > - = Def->getType()->getAs<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();
> > @@ -4025,13 +4053,13 @@
> >
> > // Do special checking on direct calls to functions.
> > if (FDecl) {
> > - if (CheckFunctionCall(FDecl, TheCall))
> > + if (CheckFunctionCall(FDecl, TheCall, Proto))
> > return ExprError();
> >
> > if (BuiltinID)
> > return CheckBuiltinFunctionCall(BuiltinID, TheCall);
> > } else if (NDecl) {
> > - if (CheckBlockCall(NDecl, TheCall))
> > + if (CheckBlockCall(NDecl, TheCall, Proto))
> > return ExprError();
> > }
> >
> >
> > Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=159159&r1=159158&r2=159159&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Jun 25 15:30:08 2012
> > @@ -10698,7 +10698,7 @@
> >
> > DiagnoseSentinelCalls(Method, LParenLoc, Args, NumArgs);
> >
> > - if (CheckFunctionCall(Method, TheCall))
> > + if (CheckFunctionCall(Method, TheCall, Proto))
> > return ExprError();
> >
> > if ((isa<CXXConstructorDecl>(CurContext) ||
> > @@ -11006,7 +11006,7 @@
> >
> > DiagnoseSentinelCalls(Method, LParenLoc, Args, NumArgs);
> >
> > - if (CheckFunctionCall(Method, TheCall))
> > + if (CheckFunctionCall(Method, TheCall, Proto))
> > return true;
> >
> > return MaybeBindToTemporary(TheCall);
> > @@ -11186,7 +11186,7 @@
> > if (CheckCallReturnType(FD->getResultType(), UDSuffixLoc, UDL, FD))
> > return ExprError();
> >
> > - if (CheckFunctionCall(FD, UDL))
> > + if (CheckFunctionCall(FD, UDL, NULL))
> > return ExprError();
> >
> > return MaybeBindToTemporary(UDL);
> >
> >
> > _______________________________________________
> > cfe-commits mailing list
> > cfe-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
> -David
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20120627/40482e9f/attachment.html>
More information about the cfe-commits
mailing list