aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r--lib/Sema/SemaExpr.cpp238
1 files changed, 161 insertions, 77 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 7fafb14591..307e1ad45e 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -455,28 +455,78 @@ Sema::ExprResult Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
}
}
+ if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) {
+ if (!MD->isStatic()) {
+ // C++ [class.mfct.nonstatic]p2:
+ // [...] if name lookup (3.4.1) resolves the name in the
+ // id-expression to a nonstatic nontype member of class X or of
+ // a base class of X, the id-expression is transformed into a
+ // class member access expression (5.2.5) using (*this) (9.3.2)
+ // as the postfix-expression to the left of the '.' operator.
+ DeclContext *Ctx = 0;
+ QualType MemberType;
+ if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
+ Ctx = FD->getDeclContext();
+ MemberType = FD->getType();
+
+ if (const ReferenceType *RefType = MemberType->getAsReferenceType())
+ MemberType = RefType->getPointeeType();
+ else if (!FD->isMutable()) {
+ unsigned combinedQualifiers
+ = MemberType.getCVRQualifiers() | MD->getTypeQualifiers();
+ MemberType = MemberType.getQualifiedType(combinedQualifiers);
+ }
+ } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+ if (!Method->isStatic()) {
+ Ctx = Method->getParent();
+ MemberType = Method->getType();
+ }
+ } else if (OverloadedFunctionDecl *Ovl
+ = dyn_cast<OverloadedFunctionDecl>(D)) {
+ for (OverloadedFunctionDecl::function_iterator
+ Func = Ovl->function_begin(),
+ FuncEnd = Ovl->function_end();
+ Func != FuncEnd; ++Func) {
+ if (CXXMethodDecl *DMethod = dyn_cast<CXXMethodDecl>(*Func))
+ if (!DMethod->isStatic()) {
+ Ctx = Ovl->getDeclContext();
+ MemberType = Context.OverloadTy;
+ break;
+ }
+ }
+ }
+
+ if (Ctx && Ctx->isCXXRecord()) {
+ QualType CtxType = Context.getTagDeclType(cast<CXXRecordDecl>(Ctx));
+ QualType ThisType = Context.getTagDeclType(MD->getParent());
+ if ((Context.getCanonicalType(CtxType)
+ == Context.getCanonicalType(ThisType)) ||
+ IsDerivedFrom(ThisType, CtxType)) {
+ // Build the implicit member access expression.
+ Expr *This = new CXXThisExpr(SourceLocation(),
+ MD->getThisType(Context));
+ return new MemberExpr(This, true, cast<NamedDecl>(D),
+ SourceLocation(), MemberType);
+ }
+ }
+ }
+ }
+
if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) {
if (MD->isStatic())
// "invalid use of member 'x' in static member function"
return Diag(Loc, diag::err_invalid_member_use_in_static_method)
- << FD->getDeclName();
- if (MD->getParent() != FD->getDeclContext())
- // "invalid use of nonstatic data member 'x'"
- return Diag(Loc, diag::err_invalid_non_static_member_use)
<< FD->getDeclName();
-
- if (FD->isInvalidDecl())
- return true;
-
- // FIXME: Handle 'mutable'.
- return new DeclRefExpr(FD,
- FD->getType().getWithAdditionalQualifiers(MD->getTypeQualifiers()),Loc);
}
+ // Any other ways we could have found the field in a well-formed
+ // program would have been turned into implicit member expressions
+ // above.
return Diag(Loc, diag::err_invalid_non_static_member_use)
<< FD->getDeclName();
}
+
if (isa<TypedefDecl>(D))
return Diag(Loc, diag::err_unexpected_typedef) << Name;
if (isa<ObjCInterfaceDecl>(D))
@@ -1409,13 +1459,87 @@ ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
<< BaseType << BaseExpr->getSourceRange();
}
+/// 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
+/// Fn is the function expression. For a C++ member function, this
+/// routine does not attempt to convert the object argument. Returns
+/// true if the call is ill-formed.
+bool
+Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
+ FunctionDecl *FDecl,
+ const FunctionTypeProto *Proto,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RParenLoc) {
+ // C99 6.5.2.2p7 - the arguments are implicitly converted, as if by
+ // assignment, to the types of the corresponding parameter, ...
+ unsigned NumArgsInProto = Proto->getNumArgs();
+ unsigned NumArgsToCheck = NumArgs;
+
+ // If too few arguments are available (and we don't have default
+ // arguments for the remaining parameters), don't make the call.
+ if (NumArgs < NumArgsInProto) {
+ if (!FDecl || NumArgs < FDecl->getMinRequiredArguments())
+ return Diag(RParenLoc, diag::err_typecheck_call_too_few_args)
+ << Fn->getType()->isBlockPointerType() << Fn->getSourceRange();
+ // Use default arguments for missing arguments
+ NumArgsToCheck = NumArgsInProto;
+ Call->setNumArgs(NumArgsInProto);
+ }
+
+ // If too many are passed and not variadic, error on the extras and drop
+ // them.
+ if (NumArgs > NumArgsInProto) {
+ if (!Proto->isVariadic()) {
+ Diag(Args[NumArgsInProto]->getLocStart(),
+ diag::err_typecheck_call_too_many_args)
+ << Fn->getType()->isBlockPointerType() << Fn->getSourceRange()
+ << SourceRange(Args[NumArgsInProto]->getLocStart(),
+ Args[NumArgs-1]->getLocEnd());
+ // This deletes the extra arguments.
+ Call->setNumArgs(NumArgsInProto);
+ }
+ NumArgsToCheck = NumArgsInProto;
+ }
+
+ // Continue to check argument types (even if we have too few/many args).
+ for (unsigned i = 0; i != NumArgsToCheck; i++) {
+ QualType ProtoArgType = Proto->getArgType(i);
+
+ Expr *Arg;
+ if (i < NumArgs)
+ Arg = Args[i];
+ else
+ Arg = new CXXDefaultArgExpr(FDecl->getParamDecl(i));
+ QualType ArgType = Arg->getType();
+
+ // Pass the argument.
+ if (PerformCopyInitialization(Arg, ProtoArgType, "passing"))
+ return true;
+
+ Call->setArg(i, Arg);
+ }
+
+ // If this is a variadic call, handle args passed through "...".
+ if (Proto->isVariadic()) {
+ // Promote the arguments (C99 6.5.2.2p7).
+ for (unsigned i = NumArgsInProto; i != NumArgs; i++) {
+ Expr *Arg = Args[i];
+ DefaultArgumentPromotion(Arg);
+ Call->setArg(i, Arg);
+ }
+ }
+
+ return false;
+}
+
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
/// This provides the location of the left/right parens and a list of comma
/// locations.
-Action::ExprResult Sema::
-ActOnCallExpr(Scope *S, ExprTy *fn, SourceLocation LParenLoc,
- ExprTy **args, unsigned NumArgs,
- SourceLocation *CommaLocs, SourceLocation RParenLoc) {
+Action::ExprResult
+Sema::ActOnCallExpr(Scope *S, ExprTy *fn, SourceLocation LParenLoc,
+ ExprTy **args, unsigned NumArgs,
+ SourceLocation *CommaLocs, SourceLocation RParenLoc) {
Expr *Fn = static_cast<Expr *>(fn);
Expr **Args = reinterpret_cast<Expr**>(args);
assert(Fn && "no function call expression");
@@ -1454,6 +1578,20 @@ ActOnCallExpr(Scope *S, ExprTy *fn, SourceLocation LParenLoc,
if (Dependent)
return new CallExpr(Fn, Args, NumArgs, Context.DependentTy, RParenLoc);
+ // Determine whether this is a call to an object (C++ [over.call.object]).
+ if (getLangOptions().CPlusPlus && Fn->getType()->isRecordType())
+ return BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs,
+ CommaLocs, RParenLoc);
+
+ // Determine whether this is a call to a member function.
+ if (getLangOptions().CPlusPlus) {
+ if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(Fn->IgnoreParens()))
+ if (isa<OverloadedFunctionDecl>(MemExpr->getMemberDecl()) ||
+ isa<CXXMethodDecl>(MemExpr->getMemberDecl()))
+ return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
+ CommaLocs, RParenLoc);
+ }
+
// If we're directly calling a function or a set of overloaded
// functions, get the appropriate declaration.
{
@@ -1482,10 +1620,6 @@ ActOnCallExpr(Scope *S, ExprTy *fn, SourceLocation LParenLoc,
Fn = NewFn;
}
- if (getLangOptions().CPlusPlus && Fn->getType()->isRecordType())
- return BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs,
- CommaLocs, RParenLoc);
-
// Promote the function operand.
UsualUnaryConversions(Fn);
@@ -1515,64 +1649,9 @@ ActOnCallExpr(Scope *S, ExprTy *fn, SourceLocation LParenLoc,
TheCall->setType(FuncT->getResultType().getNonReferenceType());
if (const FunctionTypeProto *Proto = dyn_cast<FunctionTypeProto>(FuncT)) {
- // C99 6.5.2.2p7 - the arguments are implicitly converted, as if by
- // assignment, to the types of the corresponding parameter, ...
- unsigned NumArgsInProto = Proto->getNumArgs();
- unsigned NumArgsToCheck = NumArgs;
-
- // If too few arguments are available (and we don't have default
- // arguments for the remaining parameters), don't make the call.
- if (NumArgs < NumArgsInProto) {
- if (!FDecl || NumArgs < FDecl->getMinRequiredArguments())
- return Diag(RParenLoc, diag::err_typecheck_call_too_few_args)
- << Fn->getType()->isBlockPointerType() << Fn->getSourceRange();
- // Use default arguments for missing arguments
- NumArgsToCheck = NumArgsInProto;
- TheCall->setNumArgs(NumArgsInProto);
- }
-
- // If too many are passed and not variadic, error on the extras and drop
- // them.
- if (NumArgs > NumArgsInProto) {
- if (!Proto->isVariadic()) {
- Diag(Args[NumArgsInProto]->getLocStart(),
- diag::err_typecheck_call_too_many_args)
- << Fn->getType()->isBlockPointerType() << Fn->getSourceRange()
- << SourceRange(Args[NumArgsInProto]->getLocStart(),
- Args[NumArgs-1]->getLocEnd());
- // This deletes the extra arguments.
- TheCall->setNumArgs(NumArgsInProto);
- }
- NumArgsToCheck = NumArgsInProto;
- }
-
- // Continue to check argument types (even if we have too few/many args).
- for (unsigned i = 0; i != NumArgsToCheck; i++) {
- QualType ProtoArgType = Proto->getArgType(i);
-
- Expr *Arg;
- if (i < NumArgs)
- Arg = Args[i];
- else
- Arg = new CXXDefaultArgExpr(FDecl->getParamDecl(i));
- QualType ArgType = Arg->getType();
-
- // Pass the argument.
- if (PerformCopyInitialization(Arg, ProtoArgType, "passing"))
- return true;
-
- TheCall->setArg(i, Arg);
- }
-
- // If this is a variadic call, handle args passed through "...".
- if (Proto->isVariadic()) {
- // Promote the arguments (C99 6.5.2.2p7).
- for (unsigned i = NumArgsInProto; i != NumArgs; i++) {
- Expr *Arg = Args[i];
- DefaultArgumentPromotion(Arg);
- TheCall->setArg(i, Arg);
- }
- }
+ if (ConvertArgumentsForCall(&*TheCall, Fn, FDecl, Proto, Args, NumArgs,
+ RParenLoc))
+ return true;
} else {
assert(isa<FunctionTypeNoProto>(FuncT) && "Unknown FunctionType!");
@@ -1584,6 +1663,11 @@ ActOnCallExpr(Scope *S, ExprTy *fn, SourceLocation LParenLoc,
}
}
+ if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(FDecl))
+ if (!Method->isStatic())
+ return Diag(LParenLoc, diag::err_member_call_without_object)
+ << Fn->getSourceRange();
+
// Do special checking on direct calls to functions.
if (FDecl)
return CheckFunctionCall(FDecl, TheCall.take());