diff options
| author | Douglas Gregor <dgregor@apple.com> | 2008-12-06 00:22:45 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2008-12-06 00:22:45 +0000 |
| commit | b0846b0f5101ced59627c73d370915e5f2370ace (patch) | |
| tree | dadc73d8abfbd7948d60f88cd8ce67bcedb86cd2 /clang/lib/Sema | |
| parent | 35e2cfccafd00304507e3f99ec3ecfa6168326a7 (diff) | |
| download | bcm5719-llvm-b0846b0f5101ced59627c73d370915e5f2370ace.tar.gz bcm5719-llvm-b0846b0f5101ced59627c73d370915e5f2370ace.zip | |
Add support for calls to dependent names within templates, e.g.,
template<typename T> void f(T x) {
g(x); // g is a dependent name, so don't even bother to look it up
g(); // error: g is not a dependent name
}
Note that when we see "g(", we build a CXXDependentNameExpr. However,
if none of the call arguments are type-dependent, we will force the
resolution of the name "g" and replace the CXXDependentNameExpr with
its result.
GCC actually produces a nice error message when you make this
mistake, and even offers to compile your code with -fpermissive. I'll
do the former next, but I don't plan to do the latter.
llvm-svn: 60618
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/Sema.h | 8 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 56 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 5 |
3 files changed, 59 insertions, 10 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 85cd2c873ba..b396e1c185b 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -461,7 +461,7 @@ public: SourceLocation RParenLoc); ExprResult - BuildCallToObjectOfClassType(Expr *Object, SourceLocation LParenLoc, + BuildCallToObjectOfClassType(Scope *S, Expr *Object, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation *CommaLocs, SourceLocation RParenLoc); @@ -643,7 +643,8 @@ public: ExprResult ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, DeclarationName Name, bool HasTrailingLParen, - const CXXScopeSpec *SS); + const CXXScopeSpec *SS, + bool ForceResolution = false); virtual ExprResult ActOnPredefinedExpr(SourceLocation Loc, @@ -681,7 +682,8 @@ public: /// 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. - virtual ExprResult ActOnCallExpr(ExprTy *Fn, SourceLocation LParenLoc, + virtual ExprResult ActOnCallExpr(Scope *S, ExprTy *Fn, + SourceLocation LParenLoc, ExprTy **Args, unsigned NumArgs, SourceLocation *CommaLocs, SourceLocation RParenLoc); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index e4beb74fc5d..cdca6827049 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -364,10 +364,29 @@ Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc, /// function call context. LookupCtx is only used for a C++ /// qualified-id (foo::bar) to indicate the class or namespace that /// the identifier must be a member of. +/// +/// If ForceResolution is true, then we will attempt to resolve the +/// name even if it looks like a dependent name. This option is off by +/// default. Sema::ExprResult Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, DeclarationName Name, bool HasTrailingLParen, - const CXXScopeSpec *SS) { + const CXXScopeSpec *SS, + bool ForceResolution) { + if (S->getTemplateParamParent() && Name.getAsIdentifierInfo() && + HasTrailingLParen && !SS && !ForceResolution) { + // We've seen something of the form + // identifier( + // and we are in a template, so it is likely that 's' is a + // dependent name. However, we won't know until we've parsed all + // of the call arguments. So, build a CXXDependentNameExpr node + // to represent this name. Then, if it turns out that none of the + // arguments are type-dependent, we'll force the resolution of the + // dependent name at that point. + return new CXXDependentNameExpr(Name.getAsIdentifierInfo(), + Context.DependentTy, Loc); + } + // Could be enum-constant, value decl, instance variable, etc. Decl *D; if (SS && !SS->isEmpty()) { @@ -377,7 +396,7 @@ Sema::ExprResult Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, D = LookupDecl(Name, Decl::IDNS_Ordinary, S, DC); } else D = LookupDecl(Name, Decl::IDNS_Ordinary, S); - + // If this reference is in an Objective-C method, then ivar lookup happens as // well. IdentifierInfo *II = Name.getAsIdentifierInfo(); @@ -1315,7 +1334,7 @@ ActOnMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc, /// This provides the location of the left/right parens and a list of comma /// locations. Action::ExprResult Sema:: -ActOnCallExpr(ExprTy *fn, SourceLocation LParenLoc, +ActOnCallExpr(Scope *S, ExprTy *fn, SourceLocation LParenLoc, ExprTy **args, unsigned NumArgs, SourceLocation *CommaLocs, SourceLocation RParenLoc) { Expr *Fn = static_cast<Expr *>(fn); @@ -1324,9 +1343,36 @@ ActOnCallExpr(ExprTy *fn, SourceLocation LParenLoc, FunctionDecl *FDecl = NULL; OverloadedFunctionDecl *Ovl = NULL; + // Determine whether this is a dependent call inside a C++ template, + // in which case we won't do any semantic analysis now. + bool Dependent = false; + if (Fn->isTypeDependent()) { + if (CXXDependentNameExpr *FnName = dyn_cast<CXXDependentNameExpr>(Fn)) { + if (Expr::hasAnyTypeDependentArguments(Args, NumArgs)) + Dependent = true; + else { + // Resolve the CXXDependentNameExpr to an actual identifier; + // it wasn't really a dependent name after all. + ExprResult Resolved + = ActOnDeclarationNameExpr(S, FnName->getLocation(), FnName->getName(), + /*HasTrailingLParen=*/true, + /*SS=*/0, + /*ForceResolution=*/true); + if (Resolved.isInvalid) + return true; + else { + delete Fn; + Fn = (Expr *)Resolved.Val; + } + } + } else + Dependent = true; + } else + Dependent = Expr::hasAnyTypeDependentArguments(Args, NumArgs); + // FIXME: Will need to cache the results of name lookup (including // ADL) in Fn. - if (Fn->isTypeDependent() || Expr::hasAnyTypeDependentArguments(Args, NumArgs)) + if (Dependent) return new CallExpr(Fn, Args, NumArgs, Context.DependentTy, RParenLoc); // If we're directly calling a function or a set of overloaded @@ -1358,7 +1404,7 @@ ActOnCallExpr(ExprTy *fn, SourceLocation LParenLoc, } if (getLangOptions().CPlusPlus && Fn->getType()->isRecordType()) - return BuildCallToObjectOfClassType(Fn, LParenLoc, Args, NumArgs, + return BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs, CommaLocs, RParenLoc); // Promote the function operand. diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 80bb9eda886..8a68d5be5c3 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -3102,7 +3102,8 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, OverloadedFunctionDecl *Ov /// overloaded function call operator (@c operator()) or performing a /// user-defined conversion on the object argument. Action::ExprResult -Sema::BuildCallToObjectOfClassType(Expr *Object, SourceLocation LParenLoc, +Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, + SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation *CommaLocs, SourceLocation RParenLoc) { @@ -3220,7 +3221,7 @@ Sema::BuildCallToObjectOfClassType(Expr *Object, SourceLocation LParenLoc, ImpCastExprToType(Object, Conv->getConversionType().getNonReferenceType(), Conv->getConversionType()->isReferenceType()); - return ActOnCallExpr((ExprTy*)Object, LParenLoc, (ExprTy**)Args, NumArgs, + return ActOnCallExpr(S, (ExprTy*)Object, LParenLoc, (ExprTy**)Args, NumArgs, CommaLocs, RParenLoc); } |

