summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2008-12-06 00:22:45 +0000
committerDouglas Gregor <dgregor@apple.com>2008-12-06 00:22:45 +0000
commitb0846b0f5101ced59627c73d370915e5f2370ace (patch)
treedadc73d8abfbd7948d60f88cd8ce67bcedb86cd2 /clang/lib/Sema/SemaExpr.cpp
parent35e2cfccafd00304507e3f99ec3ecfa6168326a7 (diff)
downloadbcm5719-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/SemaExpr.cpp')
-rw-r--r--clang/lib/Sema/SemaExpr.cpp56
1 files changed, 51 insertions, 5 deletions
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.
OpenPOWER on IntegriCloud