aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-11-24 19:00:30 +0000
committerJohn McCall <rjmccall@apple.com>2009-11-24 19:00:30 +0000
commitf7a1a744eba4b29ceb0f20af8f34515d892fdd64 (patch)
tree9698ed40b4b0973e9f2e64c7af2fd896b154ed43 /lib/Sema
parent909e58988b3a3bb2ad36bec03aafa1302544fd73 (diff)
Rip out TemplateIdRefExpr and make UnresolvedLookupExpr and
DependentScopeDeclRefExpr support storing templateids. Unite the common code paths between ActOnDeclarationNameExpr and ActOnTemplateIdExpr. This gets us to a point where we don't need to store function templates in the AST using TemplateNames, which is critical to ripping out OverloadedFunction. Also resolves a few FIXMEs. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89785 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/Lookup.h13
-rw-r--r--lib/Sema/Sema.h68
-rw-r--r--lib/Sema/SemaCodeComplete.cpp6
-rw-r--r--lib/Sema/SemaDeclAttr.cpp7
-rw-r--r--lib/Sema/SemaExpr.cpp506
-rw-r--r--lib/Sema/SemaExprCXX.cpp2
-rw-r--r--lib/Sema/SemaLookup.cpp6
-rw-r--r--lib/Sema/SemaOverload.cpp91
-rw-r--r--lib/Sema/SemaTemplate.cpp366
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp48
-rw-r--r--lib/Sema/TreeTransform.h196
11 files changed, 727 insertions, 582 deletions
diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h
index b30590661c..c7b574fd66 100644
--- a/lib/Sema/Lookup.h
+++ b/lib/Sema/Lookup.h
@@ -379,14 +379,14 @@ public:
class Filter {
LookupResult &Results;
unsigned I;
- bool ErasedAny;
+ bool Changed;
#ifndef NDEBUG
bool CalledDone;
#endif
friend class LookupResult;
Filter(LookupResult &Results)
- : Results(Results), I(0), ErasedAny(false)
+ : Results(Results), I(0), Changed(false)
#ifndef NDEBUG
, CalledDone(false)
#endif
@@ -413,7 +413,12 @@ public:
void erase() {
Results.Decls[--I] = Results.Decls.back();
Results.Decls.pop_back();
- ErasedAny = true;
+ Changed = true;
+ }
+
+ void replace(NamedDecl *D) {
+ Results.Decls[I-1] = D;
+ Changed = true;
}
void done() {
@@ -422,7 +427,7 @@ public:
CalledDone = true;
#endif
- if (ErasedAny)
+ if (Changed)
Results.resolveKindAfterFilter();
}
};
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 3b3b41ba21..beaccdac2f 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1389,6 +1389,16 @@ public:
UnqualifiedId &Name,
bool HasTrailingLParen,
bool IsAddressOfOperand);
+
+ OwningExprResult LookupInObjCMethod(LookupResult &R,
+ Scope *S,
+ IdentifierInfo *II);
+
+ OwningExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS,
+ DeclarationName Name,
+ SourceLocation NameLoc,
+ bool CheckForImplicitMember,
+ const TemplateArgumentListInfo *TemplateArgs);
OwningExprResult BuildDeclRefExpr(NamedDecl *D, QualType Ty,
SourceLocation Loc,
@@ -1400,26 +1410,25 @@ public:
FieldDecl *Field,
Expr *BaseObjectExpr = 0,
SourceLocation OpLoc = SourceLocation());
- OwningExprResult ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
- DeclarationName Name,
- bool HasTrailingLParen,
- const CXXScopeSpec *SS,
- bool isAddressOfOperand = false);
- OwningExprResult BuildImplicitMemberReferenceExpr(const CXXScopeSpec *SS,
- LookupResult &R);
- bool UseArgumentDependentLookup(const CXXScopeSpec *SS,
+ OwningExprResult BuildImplicitMemberReferenceExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs);
+ bool UseArgumentDependentLookup(const CXXScopeSpec &SS,
const LookupResult &R,
bool HasTrailingLParen);
- OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec *SS,
- LookupResult &R, bool ADL);
- OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec *SS,
- SourceLocation Loc,
- DeclarationName Name,
- bool NeedsADL,
- bool IsOverloaded,
- NamedDecl * const *Decls,
- unsigned NumDecls);
- OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec *SS,
+
+ OwningExprResult BuildQualifiedDeclarationNameExpr(const CXXScopeSpec &SS,
+ DeclarationName Name,
+ SourceLocation NameLoc);
+ OwningExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
+ DeclarationName Name,
+ SourceLocation NameLoc,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ bool ADL);
+ OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
SourceLocation Loc,
NamedDecl *D);
@@ -2110,7 +2119,7 @@ public:
FunctionDecl::StorageClass& SC);
DeclPtrTy ActOnConversionDeclarator(CXXConversionDecl *Conversion);
- bool isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D,
+ bool isImplicitMemberReference(const CXXScopeSpec &SS, NamedDecl *D,
SourceLocation NameLoc, QualType &ThisType,
QualType &MemberType);
@@ -2207,6 +2216,9 @@ public:
//===--------------------------------------------------------------------===//
// C++ Templates [C++ 14]
//
+ void LookupTemplateName(LookupResult &R, Scope *S, const CXXScopeSpec &SS,
+ QualType ObjectType, bool EnteringContext);
+
virtual TemplateNameKind isTemplateName(Scope *S,
const CXXScopeSpec &SS,
UnqualifiedId &Name,
@@ -2286,18 +2298,14 @@ public:
DeclSpec::TST TagSpec,
SourceLocation TagLoc);
- OwningExprResult BuildTemplateIdExpr(NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
- TemplateName Template,
- SourceLocation TemplateNameLoc,
+ OwningExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ bool RequiresADL,
+ const TemplateArgumentListInfo &TemplateArgs);
+ OwningExprResult BuildQualifiedTemplateIdExpr(const CXXScopeSpec &SS,
+ DeclarationName Name,
+ SourceLocation NameLoc,
const TemplateArgumentListInfo &TemplateArgs);
-
- OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS,
- TemplateTy Template,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgs,
- SourceLocation RAngleLoc);
virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
const CXXScopeSpec &SS,
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index a555a64ddf..b4947242bd 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -1967,8 +1967,10 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName,
if (!CDecl && FName->isStr("super")) {
// "super" may be the name of a variable, in which case we are
// probably calling an instance method.
- OwningExprResult Super = ActOnDeclarationNameExpr(S, FNameLoc, FName,
- false, 0, false);
+ CXXScopeSpec SS;
+ UnqualifiedId id;
+ id.setIdentifier(FName, FNameLoc);
+ OwningExprResult Super = ActOnIdExpression(S, SS, id, false, false);
return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get(),
SelIdents, NumSelIdents);
}
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 3fa7d9cdde..2405d52890 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -177,9 +177,10 @@ static void HandleExtVectorTypeAttr(Scope *scope, Decl *d,
// Special case where the argument is a template id.
if (Attr.getParameterName()) {
- sizeExpr = S.ActOnDeclarationNameExpr(scope, Attr.getLoc(),
- Attr.getParameterName(),
- false, 0, false).takeAs<Expr>();
+ CXXScopeSpec SS;
+ UnqualifiedId id;
+ id.setIdentifier(Attr.getParameterName(), Attr.getLoc());
+ sizeExpr = S.ActOnIdExpression(scope, SS, id, false, false).takeAs<Expr>();
} else {
// check the attribute arguments.
if (Attr.getNumArgs() != 1) {
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 9d7a42172c..50fd5ec9b1 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -617,202 +617,140 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
return Owned(Result);
}
+static void DecomposeTemplateName(LookupResult &R, TemplateName TName) {
+ if (TemplateDecl *TD = TName.getAsTemplateDecl())
+ R.addDecl(TD);
+ else if (OverloadedFunctionDecl *OD
+ = TName.getAsOverloadedFunctionDecl())
+ for (OverloadIterator I(OD), E; I != E; ++I)
+ R.addDecl(*I);
+
+ R.resolveKind();
+}
+
Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
const CXXScopeSpec &SS,
- UnqualifiedId &Name,
+ UnqualifiedId &Id,
bool HasTrailingLParen,
- bool IsAddressOfOperand) {
- assert(!(IsAddressOfOperand && HasTrailingLParen) &&
+ bool isAddressOfOperand) {
+ assert(!(isAddressOfOperand && HasTrailingLParen) &&
"cannot be direct & operand and have a trailing lparen");
- if (Name.getKind() == UnqualifiedId::IK_TemplateId) {
+ if (SS.isInvalid())
+ return ExprError();
+
+ TemplateArgumentListInfo ExplicitTemplateArgs;
+
+ // Decompose the UnqualifiedId into the following data.
+ DeclarationName Name;
+ SourceLocation NameLoc;
+ const TemplateArgumentListInfo *TemplateArgs;
+ if (Id.getKind() == UnqualifiedId::IK_TemplateId) {
+ ExplicitTemplateArgs.setLAngleLoc(Id.TemplateId->LAngleLoc);
+ ExplicitTemplateArgs.setRAngleLoc(Id.TemplateId->RAngleLoc);
+
ASTTemplateArgsPtr TemplateArgsPtr(*this,
- Name.TemplateId->getTemplateArgs(),
- Name.TemplateId->NumArgs);
- return ActOnTemplateIdExpr(SS,
- TemplateTy::make(Name.TemplateId->Template),
- Name.TemplateId->TemplateNameLoc,
- Name.TemplateId->LAngleLoc,
- TemplateArgsPtr,
- Name.TemplateId->RAngleLoc);
- }
-
- // FIXME: We lose a bunch of source information by doing this. Later,
- // we'll want to merge ActOnDeclarationNameExpr's logic into
- // ActOnIdExpression.
- return ActOnDeclarationNameExpr(S,
- Name.StartLocation,
- GetNameFromUnqualifiedId(Name),
- HasTrailingLParen,
- &SS,
- IsAddressOfOperand);
-}
+ Id.TemplateId->getTemplateArgs(),
+ Id.TemplateId->NumArgs);
+ translateTemplateArguments(TemplateArgsPtr, ExplicitTemplateArgs);
+ TemplateArgsPtr.release();
-/// ActOnDeclarationNameExpr - The parser has read some kind of name
-/// (e.g., a C++ id-expression (C++ [expr.prim]p1)). This routine
-/// performs lookup on that name and returns an expression that refers
-/// to that name. This routine isn't directly called from the parser,
-/// because the parser doesn't know about DeclarationName. Rather,
-/// this routine is called by ActOnIdExpression, which contains a
-/// parsed UnqualifiedId.
-///
-/// HasTrailingLParen indicates whether this identifier is used in a
-/// 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.
-///
-/// isAddressOfOperand means that this expression is the direct operand
-/// of an address-of operator. This matters because this is the only
-/// situation where a qualified name referencing a non-static member may
-/// appear outside a member function of this class.
-Sema::OwningExprResult
-Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
- DeclarationName Name, bool HasTrailingLParen,
- const CXXScopeSpec *SS,
- bool isAddressOfOperand) {
- // Could be enum-constant, value decl, instance variable, etc.
- if (SS && SS->isInvalid())
- return ExprError();
+ TemplateName TName =
+ TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>();
- // Determine whether this is a member of an unknown specialization.
- if (SS && SS->isSet() && !computeDeclContext(*SS, false)) {
- return Owned(new (Context) DependentScopeDeclRefExpr(Name, Context.DependentTy,
- Loc, SS->getRange(),
- static_cast<NestedNameSpecifier *>(SS->getScopeRep()),
- isAddressOfOperand));
+ Name = Context.getNameForTemplate(TName);
+ NameLoc = Id.TemplateId->TemplateNameLoc;
+ TemplateArgs = &ExplicitTemplateArgs;
+ } else {
+ Name = GetNameFromUnqualifiedId(Id);
+ NameLoc = Id.StartLocation;
+ TemplateArgs = 0;
}
- LookupResult Lookup(*this, Name, Loc, LookupOrdinaryName);
- LookupParsedName(Lookup, S, SS, true);
+ IdentifierInfo *II = Name.getAsIdentifierInfo();
- if (Lookup.isAmbiguous())
- return ExprError();
+ // C++ [temp.dep.expr]p3:
+ // An id-expression is type-dependent if it contains:
+ // -- a nested-name-specifier that contains a class-name that
+ // names a dependent type.
+ // Determine whether this is a member of an unknown specialization;
+ // we need to handle these differently.
+ if (SS.isSet() && !computeDeclContext(SS, false)) {
+ bool CheckForImplicitMember = !isAddressOfOperand;
- // If this reference is in an Objective-C method, then ivar lookup happens as
- // well.
- IdentifierInfo *II = Name.getAsIdentifierInfo();
- if (II && getCurMethodDecl()) {
- // There are two cases to handle here. 1) scoped lookup could have failed,
- // in which case we should look for an ivar. 2) scoped lookup could have
- // found a decl, but that decl is outside the current instance method (i.e.
- // a global variable). In these two cases, we do a lookup for an ivar with
- // this name, if the lookup sucedes, we replace it our current decl.
-
- // FIXME: we should change lookup to do this.
-
- // If we're in a class method, we don't normally want to look for
- // ivars. But if we don't find anything else, and there's an
- // ivar, that's an error.
- bool IsClassMethod = getCurMethodDecl()->isClassMethod();
-
- bool LookForIvars;
- if (Lookup.empty())
- LookForIvars = true;
- else if (IsClassMethod)
- LookForIvars = false;
- else
- LookForIvars = (Lookup.isSingleResult() &&
- Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod());
+ return ActOnDependentIdExpression(SS, Name, NameLoc,
+ CheckForImplicitMember,
+ TemplateArgs);
+ }
- if (LookForIvars) {
- ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface();
- ObjCInterfaceDecl *ClassDeclared;
- if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
- // Diagnose using an ivar in a class method.
- if (IsClassMethod)
- return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method)
- << IV->getDeclName());
-
- // If we're referencing an invalid decl, just return this as a silent
- // error node. The error diagnostic was already emitted on the decl.
- if (IV->isInvalidDecl())
- return ExprError();
+ // Perform the required lookup.
+ LookupResult R(*this, Name, NameLoc, LookupOrdinaryName);
+ if (TemplateArgs) {
+ TemplateName TName =
+ TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>();
- // Check if referencing a field with __attribute__((deprecated)).
- if (DiagnoseUseOfDecl(IV, Loc))
- return ExprError();
+ // Just re-use the lookup done by isTemplateName.
+ DecomposeTemplateName(R, TName);
+ } else {
+ LookupParsedName(R, S, &SS, true);
- // Diagnose the use of an ivar outside of the declaring class.
- if (IV->getAccessControl() == ObjCIvarDecl::Private &&
- ClassDeclared != IFace)
- Diag(Loc, diag::error_private_ivar_access) << IV->getDeclName();
-
- // FIXME: This should use a new expr for a direct reference, don't
- // turn this into Self->ivar, just return a BareIVarExpr or something.
- IdentifierInfo &II = Context.Idents.get("self");
- UnqualifiedId SelfName;
- SelfName.setIdentifier(&II, SourceLocation());
- CXXScopeSpec SelfScopeSpec;
- OwningExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec,
- SelfName, false, false);
- MarkDeclarationReferenced(Loc, IV);
- return Owned(new (Context)
- ObjCIvarRefExpr(IV, IV->getType(), Loc,
- SelfExpr.takeAs<Expr>(), true, true));
- }
- } else if (getCurMethodDecl()->isInstanceMethod()) {
- // We should warn if a local variable hides an ivar.
- ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface();
- ObjCInterfaceDecl *ClassDeclared;
- if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
- if (IV->getAccessControl() != ObjCIvarDecl::Private ||
- IFace == ClassDeclared)
- Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName();
- }
- }
- // Needed to implement property "super.method" notation.
- if (Lookup.empty() && II->isStr("super")) {
- QualType T;
+ // If this reference is in an Objective-C method, then we need to do
+ // some special Objective-C lookup, too.
+ if (!SS.isSet() && II && getCurMethodDecl()) {
+ OwningExprResult E(LookupInObjCMethod(R, S, II));
+ if (E.isInvalid())
+ return ExprError();
- if (getCurMethodDecl()->isInstanceMethod())
- T = Context.getObjCObjectPointerType(Context.getObjCInterfaceType(
- getCurMethodDecl()->getClassInterface()));
- else
- T = Context.getObjCClassType();
- return Owned(new (Context) ObjCSuperExpr(Loc, T));
+ Expr *Ex = E.takeAs<Expr>();
+ if (Ex) return Owned(Ex);
}
}
+ if (R.isAmbiguous())
+ return ExprError();
+
// Determine whether this name might be a candidate for
// argument-dependent lookup.
- bool ADL = UseArgumentDependentLookup(SS, Lookup, HasTrailingLParen);
+ bool ADL = UseArgumentDependentLookup(SS, R, HasTrailingLParen);
- if (Lookup.empty() && !ADL) {
+ if (R.empty() && !ADL) {
// Otherwise, this could be an implicitly declared function reference (legal
- // in C90, extension in C99).
- if (HasTrailingLParen && II &&
- !getLangOptions().CPlusPlus) { // Not in C++.
- NamedDecl *D = ImplicitlyDefineFunction(Loc, *II, S);
- if (D) Lookup.addDecl(D);
- } else {
- // If this name wasn't predeclared and if this is not a function call,
- // diagnose the problem.
- if (SS && !SS->isEmpty())
- return ExprError(Diag(Loc, diag::err_no_member)
- << Name << computeDeclContext(*SS, false)
- << SS->getRange());
+ // in C90, extension in C99, forbidden in C++).
+ if (HasTrailingLParen && II && !getLangOptions().CPlusPlus) {
+ NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *II, S);
+ if (D) R.addDecl(D);
+ }
+
+ // If this name wasn't predeclared and if this is not a function
+ // call, diagnose the problem.
+ if (R.empty()) {
+ if (!SS.isEmpty())
+ return ExprError(Diag(NameLoc, diag::err_no_member)
+ << Name << computeDeclContext(SS, false)
+ << SS.getRange());
else if (Name.getNameKind() == DeclarationName::CXXOperatorName ||
Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
- return ExprError(Diag(Loc, diag::err_undeclared_use)
- << Name.getAsString());
+ return ExprError(Diag(NameLoc, diag::err_undeclared_use)
+ << Name);
else
- return ExprError(Diag(Loc, diag::err_undeclared_var_use) << Name);
+ return ExprError(Diag(NameLoc, diag::err_undeclared_var_use) << Name);
}
}
- if (VarDecl *Var = Lookup.getAsSingle<VarDecl>()) {
+ // This is guaranteed from this point on.
+ assert(!R.empty() || ADL);
+
+ if (VarDecl *Var = R.getAsSingle<VarDecl>()) {
// Warn about constructs like:
// if (void *X = foo()) { ... } else { X }.
// In the else block, the pointer is always false.
- // FIXME: In a template instantiation, we don't have scope
- // information to check this property.
if (Var->isDeclaredInCondition() && Var->getType()->isScalarType()) {
Scope *CheckS = S;
while (CheckS && CheckS->getControlParent()) {
if (CheckS->isWithinElse() &&
CheckS->getControlParent()->isDeclScope(DeclPtrTy::make(Var))) {
- ExprError(Diag(Loc, diag::warn_value_always_zero)
+ ExprError(Diag(NameLoc, diag::warn_value_always_zero)
<< Var->getDeclName()
<< (Var->getType()->isPointerType()? 2 :
Var->getType()->isBooleanType()? 1 : 0));
@@ -823,21 +761,21 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
CheckS = CheckS->getParent();
}
}
- } else if (FunctionDecl *Func = Lookup.getAsSingle<FunctionDecl>()) {
+ } else if (FunctionDecl *Func = R.getAsSingle<FunctionDecl>()) {
if (!getLangOptions().CPlusPlus && !Func->hasPrototype()) {
// C99 DR 316 says that, if a function type comes from a
// function definition (without a prototype), that type is only
// used for checking compatibility. Therefore, when referencing
// the function, we pretend that we don't have the full function
// type.
- if (DiagnoseUseOfDecl(Func, Loc))
+ if (DiagnoseUseOfDecl(Func, NameLoc))
return ExprError();
QualType T = Func->getType();
QualType NoProtoType = T;
if (const FunctionProtoType *Proto = T->getAs<FunctionProtoType>())
NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType());
- return BuildDeclRefExpr(Func, NoProtoType, Loc, SS);
+ return BuildDeclRefExpr(Func, NoProtoType, NameLoc, &SS);
}
}
@@ -853,19 +791,141 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
// calculate them both in one pass if that proves important for
// performance.
if (!ADL) {
- bool isAbstractMemberPointer =
- (isAddressOfOperand && SS && !SS->isEmpty());
+ bool isAbstractMemberPointer = (isAddressOfOperand && !SS.isEmpty());
+
+ if (!isAbstractMemberPointer && !R.empty() &&
+ isa<CXXRecordDecl>((*R.begin())->getDeclContext())) {
+ return BuildImplicitMemberReferenceExpr(SS, R, TemplateArgs);
+ }
+ }
+
+ if (TemplateArgs)
+ return BuildTemplateIdExpr(SS, R, ADL, *TemplateArgs);
+
+ return BuildDeclarationNameExpr(SS, R, ADL);
+}
+
+/// ActOnDeclarationNameExpr - Build a C++ qualified declaration name,
+/// generally during template instantiation. There's a large number
+/// of things which don't need to be done along this path.
+Sema::OwningExprResult
+Sema::BuildQualifiedDeclarationNameExpr(const CXXScopeSpec &SS,
+ DeclarationName Name,
+ SourceLocation NameLoc) {
+ DeclContext *DC;
+ if (!(DC = computeDeclContext(SS, false)) ||
+ DC->isDependentContext() ||
+ RequireCompleteDeclContext(SS))
+ return BuildDependentDeclRefExpr(SS, Name, NameLoc, 0);
+
+ LookupResult R(*this, Name, NameLoc, LookupOrdinaryName);
+ LookupQualifiedName(R, DC);
+
+ if (R.isAmbiguous())
+ return ExprError();
+
+ if (R.empty()) {
+ Diag(NameLoc, diag::err_no_member) << Name << DC << SS.getRange();
+ return ExprError();
+ }
+
+ return BuildDeclarationNameExpr(SS, R, /*ADL*/ false);
+}
+
+/// LookupInObjCMethod - The parser has read a name in, and Sema has
+/// detected that we're currently inside an ObjC method. Perform some
+/// additional lookup.
+///
+/// Ideally, most of this would be done by lookup, but there's
+/// actually quite a lot of extra work involved.
+///
+/// Returns a null sentinel to indicate trivial success.
+Sema::OwningExprResult
+Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
+ IdentifierInfo *II) {
+ SourceLocation Loc = Lookup.getNameLoc();
+
+ // There are two cases to handle here. 1) scoped lookup could have failed,
+ // in which case we should look for an ivar. 2) scoped lookup could have
+ // found a decl, but that decl is outside the current instance method (i.e.
+ // a global variable). In these two cases, we do a lookup for an ivar with
+ // this name, if the lookup sucedes, we replace it our current decl.
+
+ // If we're in a class method, we don't normally want to look for
+ // ivars. But if we don't find anything else, and there's an
+ // ivar, that's an error.
+ bool IsClassMethod = getCurMethodDecl()->isClassMethod();
+
+ bool LookForIvars;
+ if (Lookup.empty())
+ LookForIvars = true;
+ else if (IsClassMethod)
+ LookForIvars = false;
+ else
+ LookForIvars = (Lookup.isSingleResult() &&
+ Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod());
+
+ if (LookForIvars) {
+ ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface();
+ ObjCInterfaceDecl *ClassDeclared;
+ if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
+ // Diagnose using an ivar in a class method.
+ if (IsClassMethod)
+ return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method)
+ << IV->getDeclName());
+
+ // If we're referencing an invalid decl, just return this as a silent
+ // error node. The error diagnostic was already emitted on the decl.
+ if (IV->isInvalidDecl())
+ return ExprError();
+
+ // Check if referencing a field with __attribute__((deprecated)).
+ if (DiagnoseUseOfDecl(IV, Loc))
+ return ExprError();
- if (!isAbstractMemberPointer && !Lookup.empty() &&
- isa<CXXRecordDecl>((*Lookup.begin())->getDeclContext())) {
- return BuildImplicitMemberReferenceExpr(SS, Lookup);
+ // Diagnose the use of an ivar outside of the declaring class.
+ if (IV->getAccessControl() == ObjCIvarDecl::Private &&
+ ClassDeclared != IFace)
+ Diag(Loc, diag::error_private_ivar_access) << IV->getDeclName();
+
+ // FIXME: This should use a new expr for a direct reference, don't
+ // turn this into Self->ivar, just return a BareIVarExpr or something.
+ IdentifierInfo &II = Context.Idents.get("self");
+ UnqualifiedId SelfName;
+ SelfName.setIdentifier(&II, SourceLocation());
+ CXXScopeSpec SelfScopeSpec;
+ OwningExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec,
+ SelfName, false, false);
+ MarkDeclarationReferenced(Loc, IV);
+ return Owned(new (Context)
+ ObjCIvarRefExpr(IV, IV->getType(), Loc,
+ SelfExpr.takeAs<Expr>(), true, true));
+ }
+ } else if (getCurMethodDecl()->isInstanceMethod()) {
+ // We should warn if a local variable hides an ivar.
+ ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface();
+ ObjCInterfaceDecl *ClassDeclared;
+ if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
+ if (IV->getAccessControl() != ObjCIvarDecl::Private ||
+ IFace == ClassDeclared)
+ Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName();
}
}
- assert(Lookup.getResultKind() != LookupResult::FoundUnresolvedValue &&
- "found UnresolvedUsingValueDecl in non-class scope");
+ // Needed to implement property "super.method" notation.
+ if (Lookup.empty() && II->isStr("super")) {
+ QualType T;
+
+ if (getCurMethodDecl()->isInstanceMethod())
+ T = Context.getObjCObjectPointerType(Context.getObjCInterfaceType(
+ getCurMethodDecl()->getClassInterface()));
+ else
+ T = Context.getObjCClassType();
+ return Owned(new (Context) ObjCSuperExpr(Loc, T));
+ }
- return BuildDeclarationNameExpr(SS, Lookup, ADL);
+ // Sentinel value saying that we didn't do anything special.
+ return Owned((Expr*) 0);
}
/// \brief Cast member's object to its own class if necessary.
@@ -899,29 +959,35 @@ Sema::PerformObjectMemberConversion(Expr *&From, NamedDecl *Member) {
/// \brief Build a MemberExpr AST node.
static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,
const CXXScopeSpec *SS, NamedDecl *Member,
- SourceLocation Loc, QualType Ty) {
- if (SS && SS->isSet())
- return MemberExpr::Create(C, Base, isArrow,
- (NestedNameSpecifier *)SS->getScopeRep(),
- SS->getRange(), Member, Loc,
- // FIXME: Explicit template argument lists
- 0, Ty);
-
- return new (C) MemberExpr(Base, isArrow, Member, Loc, Ty);
+ SourceLocation Loc, QualType Ty,
+ const TemplateArgumentListInfo *TemplateArgs = 0) {
+ NestedNameSpecifier *Qualifier = 0;
+ SourceRange QualifierRange;
+ if (SS && SS->isSet()) {
+ Qualifier = (NestedNameSpecifier *) SS->getScopeRep();
+ QualifierRange = SS->getRange();
+ }
+
+ return MemberExpr::Create(C, Base, isArrow, Qualifier, QualifierRange,
+ Member, Loc, TemplateArgs, Ty);
}
/// Builds an implicit member access expression from the given
/// unqualified lookup set, which is known to contain only class
/// members.
Sema::OwningExprResult
-Sema::BuildImplicitMemberReferenceExpr(const CXXScopeSpec *SS,
- LookupResult &R) {
+Sema::BuildImplicitMemberReferenceExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ assert(!R.empty() && !R.isAmbiguous());
+
NamedDecl *D = R.getAsSingleDecl(Context);
SourceLocation Loc = R.getNameLoc();
// We may have found a field within an anonymous union or struct
// (C++ [class.union]).
// FIXME: This needs to happen post-isImplicitMemberReference?
+ // FIXME: template-ids inside anonymous structs?
if (FieldDecl *FD = dyn_cast<FieldDecl>(D))
if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion())
return BuildAnonymousStructUnionMemberReference(Loc, FD);
@@ -938,13 +1004,14 @@ Sema::BuildImplicitMemberReferenceExpr(const CXXScopeSpec *SS,
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
// Don't diagnose the use of a virtual member function unless it's
// explicitly qualified.
- if (MD->isVirtual() && (!SS || !SS->isSet()))
+ if (MD->isVirtual() && !SS.isSet())
ShouldCheckUse = false;
}
if (ShouldCheckUse && DiagnoseUseOfDecl(D, Loc))
return ExprError();
- return Owned(BuildMemberExpr(Context, This, true, SS, D, Loc, MemberType));
+ return Owned(BuildMemberExpr(Context, This, true, &SS, D, Loc, MemberType,
+ TemplateArgs));
}
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
@@ -973,10 +1040,13 @@ Sema::BuildImplicitMemberReferenceExpr(const CXXScopeSpec *SS,
// We're not in an implicit member-reference context, but the lookup
// results might not require an instance. Try to build a non-member
// decl reference.
+ if (TemplateArgs)
+ return BuildTemplateIdExpr(SS, R, /* ADL */ false, *TemplateArgs);
+
return BuildDeclarationNameExpr(SS, R, /*ADL*/ false);
}
-bool Sema::UseArgumentDependentLookup(const CXXScopeSpec *SS,
+bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS,
const LookupResult &R,
bool HasTrailingLParen) {
// Only when used directly as the postfix-expression of a call.
@@ -984,7 +1054,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec *SS,
return false;
// Never if a scope specifier was provided.
- if (SS && SS->isSet())
+ if (SS.isSet())
return false;
// Only in C++ or ObjC++.
@@ -1056,11 +1126,13 @@ static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) {
}
Sema::OwningExprResult
-Sema::BuildDeclarationNameExpr(const CXXScopeSpec *SS,
+Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
LookupResult &R,
bool NeedsADL) {
assert(R.getResultKind() != LookupResult::FoundUnresolvedValue);
+ // If this isn't an overloaded result and we don't need ADL, just
+ // build an ordinary singleton decl ref.
if (!NeedsADL && !R.isOverloadedResult())
return BuildDeclarationNameExpr(SS, R.getNameLoc(), R.getFoundDecl());
@@ -1071,10 +1143,12 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec *SS,
CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl()))
return ExprError();
+ bool Dependent
+ = Unres