diff options
author | John McCall <rjmccall@apple.com> | 2011-08-27 01:09:30 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-08-27 01:09:30 +0000 |
commit | 5f8d604246976a93a73549b07bbc8ee0b2061b50 (patch) | |
tree | 77e085a2358201b9007429ba7cec2b156f556a3a /lib | |
parent | 6748ae15b3eed61b3b61f9b77470a802a1643fbb (diff) |
The lvalue-to-rvalue on structs in C++ is actually part
of default argument promotion and needs to happen unconditionally.
This is particularly semantically important in C++0x.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138691 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 29 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 30 |
2 files changed, 42 insertions, 17 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 530f81289a..30c247f987 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/Sema/Initialization.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/ScopeInfo.h" @@ -396,6 +397,30 @@ bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) { return false; } +/// checkBuiltinArgument - Given a call to a builtin function, perform +/// normal type-checking on the given argument, updating the call in +/// place. This is useful when a builtin function requires custom +/// type-checking for some of its arguments but not necessarily all of +/// them. +/// +/// Returns true on error. +static bool checkBuiltinArgument(Sema &S, CallExpr *E, unsigned ArgIndex) { + FunctionDecl *Fn = E->getDirectCallee(); + assert(Fn && "builtin call without direct callee!"); + + ParmVarDecl *Param = Fn->getParamDecl(ArgIndex); + InitializedEntity Entity = + InitializedEntity::InitializeParameter(S.Context, Param); + + ExprResult Arg = E->getArg(0); + Arg = S.PerformCopyInitialization(Entity, SourceLocation(), Arg); + if (Arg.isInvalid()) + return true; + + E->setArg(ArgIndex, Arg.take()); + return false; +} + /// SemaBuiltinAtomicOverloaded - We have a call to a function like /// __sync_fetch_and_add, which is an overloaded function based on the pointer /// type of its first argument. The main ActOnCallExpr routines have already @@ -661,6 +686,10 @@ bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) { << 0 /*function call*/ << 2 << TheCall->getNumArgs(); } + // Type-check the first argument normally. + if (checkBuiltinArgument(*this, TheCall, 0)) + return true; + // Determine whether the current function is variadic or not. BlockScopeInfo *CurBlock = getCurBlock(); bool isVariadic; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 28ec97f652..65c9cccaf1 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -443,6 +443,18 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) { if (Ty->isSpecificBuiltinType(BuiltinType::Float)) E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).take(); + // C++ includes lvalue-to-rvalue conversion as a default argument + // promotion. If we have a gl-value, initialize a temporary. + if (getLangOptions().CPlusPlus && E->isGLValue()) { + ExprResult Temp = PerformCopyInitialization( + InitializedEntity::InitializeTemporary(E->getType()), + E->getExprLoc(), + Owned(E)); + if (Temp.isInvalid()) + return ExprError(); + E = Temp.get(); + } + return Owned(E); } @@ -460,19 +472,13 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, return ExprError(); E = ExprRes.take(); - // __builtin_va_start takes the second argument as a "varargs" argument, but - // it doesn't actually do anything with it. It doesn't need to be non-pod - // etc. - if (FDecl && FDecl->getBuiltinID() == Builtin::BI__builtin_va_start) - return Owned(E); - // 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) << E->getType() << CT)) return ExprError(); - + if (!E->getType().isPODType(Context)) { // C++0x [expr.call]p7: // Passing a potentially-evaluated argument of class type (Clause 9) @@ -519,16 +525,6 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, if (Comma.isInvalid()) return ExprError(); E = Comma.get(); - - // Use that to initialize a temporary, or else we might get an - // l-value in a varargs position. - ExprResult Temp = PerformCopyInitialization( - InitializedEntity::InitializeTemporary(E->getType()), - E->getLocStart(), - Owned(E)); - if (Temp.isInvalid()) - return ExprError(); - E = Temp.get(); } } |