diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/Sema.h | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 40 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 114 |
3 files changed, 34 insertions, 125 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 3f8babbbbe9..8503887a617 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -1438,7 +1438,7 @@ public: OwningExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS, DeclarationName Name, SourceLocation NameLoc, - bool CheckForImplicitMember, + bool isAddressOfOperand, const TemplateArgumentListInfo *TemplateArgs); OwningExprResult BuildDeclRefExpr(NamedDecl *D, QualType Ty, @@ -1549,8 +1549,7 @@ public: DeclPtrTy ObjCImpDecl); bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + const CXXScopeSpec &SS, const LookupResult &R); OwningExprResult ActOnDependentMemberExpr(ExprArg Base, diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 36ab6ed44bd..ae6ba321a22 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -901,10 +901,8 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, // Determine whether this is a member of an unknown specialization; // we need to handle these differently. if (SS.isSet() && IsDependentIdExpression(*this, SS)) { - bool CheckForImplicitMember = !isAddressOfOperand; - return ActOnDependentIdExpression(SS, Name, NameLoc, - CheckForImplicitMember, + isAddressOfOperand, TemplateArgs); } @@ -2140,15 +2138,18 @@ Sema::ActOnDependentMemberExpr(ExprArg Base, QualType BaseType, static void DiagnoseQualifiedMemberReference(Sema &SemaRef, Expr *BaseExpr, QualType BaseType, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + const CXXScopeSpec &SS, const LookupResult &R) { - DeclContext *DC = R.getRepresentativeDecl()->getDeclContext(); + // If this is an implicit member access, use a different set of + // diagnostics. + if (!BaseExpr) + return DiagnoseInstanceReference(SemaRef, SS, R); // FIXME: this is an exceedingly lame diagnostic for some of the more // complicated cases here. + DeclContext *DC = R.getRepresentativeDecl()->getDeclContext(); SemaRef.Diag(R.getNameLoc(), diag::err_not_direct_base_or_virtual) - << QualifierRange << DC << BaseType; + << SS.getRange() << DC << BaseType; } // Check whether the declarations we found through a nested-name @@ -2165,8 +2166,7 @@ static void DiagnoseQualifiedMemberReference(Sema &SemaRef, // we actually pick through overload resolution is from a superclass. bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + const CXXScopeSpec &SS, const LookupResult &R) { const RecordType *BaseRT = BaseType->getAs<RecordType>(); if (!BaseRT) { @@ -2195,8 +2195,7 @@ bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr, return false; } - DiagnoseQualifiedMemberReference(*this, BaseExpr, BaseType, - Qualifier, QualifierRange, R); + DiagnoseQualifiedMemberReference(*this, BaseExpr, BaseType, SS, R); return true; } @@ -2216,6 +2215,12 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, // nested-name-specifier. DC = SemaRef.computeDeclContext(SS, false); + if (SemaRef.RequireCompleteDeclContext(SS)) { + SemaRef.Diag(SS.getRange().getEnd(), diag::err_typecheck_incomplete_tag) + << SS.getRange() << DC; + return true; + } + assert(DC && "Cannot handle non-computable dependent contexts in lookup"); if (!isa<TypeDecl>(DC)) { @@ -2240,7 +2245,8 @@ Sema::BuildMemberReferenceExpr(ExprArg BaseArg, QualType BaseType, const TemplateArgumentListInfo *TemplateArgs) { Expr *Base = BaseArg.takeAs<Expr>(); - if (BaseType->isDependentType()) + if (BaseType->isDependentType() || + (SS.isSet() && isDependentScopeSpecifier(SS))) return ActOnDependentMemberExpr(ExprArg(*this, Base), BaseType, IsArrow, OpLoc, SS, FirstQualifierInScope, @@ -2311,11 +2317,11 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType, return ExprError(); } - // We can't always diagnose the problem yet: it's permitted for - // lookup to find things from an invalid context as long as they - // don't get picked by overload resolution. - if (SS.isSet() && CheckQualifiedMemberReference(BaseExpr, BaseType, - Qualifier, SS.getRange(), R)) + // Diagnose qualified lookups that find only declarations from a + // non-base type. Note that it's okay for lookup to find + // declarations from a non-base type as long as those aren't the + // ones picked by overload resolution. + if (SS.isSet() && CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R)) return ExprError(); // Construct an unresolved result if we in fact got an unresolved diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 5f5d891a226..565581a138b 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -248,119 +248,23 @@ void Sema::LookupTemplateName(LookupResult &Found, } } -/// Constructs a full type for the given nested-name-specifier. -static QualType GetTypeForQualifier(ASTContext &Context, - NestedNameSpecifier *Qualifier) { - // Three possibilities: - - // 1. A namespace (global or not). - assert(!Qualifier->getAsNamespace() && "can't construct type for namespace"); - - // 2. A type (templated or not). - Type *Ty = Qualifier->getAsType(); - if (Ty) return QualType(Ty, 0); - - // 3. A dependent identifier. - assert(Qualifier->getAsIdentifier()); - return Context.getTypenameType(Qualifier->getPrefix(), - Qualifier->getAsIdentifier()); -} - -static bool HasDependentTypeAsBase(ASTContext &Context, - CXXRecordDecl *Record, - CanQualType T) { - for (CXXRecordDecl::base_class_iterator I = Record->bases_begin(), - E = Record->bases_end(); I != E; ++I) { - CanQualType BaseT = Context.getCanonicalType((*I).getType()); - if (BaseT == T) - return true; - - // We have to recurse here to cover some really bizarre cases. - // Obviously, we can only have the dependent type as an indirect - // base class through a dependent base class, and usually it's - // impossible to know which instantiation a dependent base class - // will have. But! If we're actually *inside* the dependent base - // class, then we know its instantiation and can therefore be - // reasonably expected to look into it. - - // template <class T> class A : Base<T> { - // class Inner : A<T> { - // void foo() { - // Base<T>::foo(); // statically known to be an implicit member - // reference - // } - // }; - // }; - - CanQual<RecordType> RT = BaseT->getAs<RecordType>(); - - // Base might be a dependent member type, in which case we - // obviously can't look into it. - if (!RT) continue; - - CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(RT->getDecl()); - if (BaseRecord->isDefinition() && - HasDependentTypeAsBase(Context, BaseRecord, T)) - return true; - } - - return false; -} - -/// Checks whether the given dependent nested-name specifier -/// introduces an implicit member reference. This is only true if the -/// nested-name specifier names a type identical to one of the current -/// instance method's context's (possibly indirect) base classes. -static bool IsImplicitDependentMemberReference(Sema &SemaRef, - NestedNameSpecifier *Qualifier, - QualType &ThisType) { - // If the context isn't a C++ method, then it isn't an implicit - // member reference. - CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(SemaRef.CurContext); - if (!MD || MD->isStatic()) - return false; - - ASTContext &Context = SemaRef.Context; - - // We want to check whether the method's context is known to inherit - // from the type named by the nested name specifier. The trivial - // case here is: - // template <class T> class Base { ... }; - // template <class T> class Derived : Base<T> { - // void foo() { - // Base<T>::foo(); - // } - // }; - - QualType QT = GetTypeForQualifier(Context, Qualifier); - CanQualType T = Context.getCanonicalType(QT); - - // And now, just walk the non-dependent type hierarchy, trying to - // find the given type as a literal base class. - CXXRecordDecl *Record = cast<CXXRecordDecl>(MD->getParent()); - if (Context.getCanonicalType(Context.getTypeDeclType(Record)) == T || - HasDependentTypeAsBase(Context, Record, T)) { - ThisType = MD->getThisType(Context); - return true; - } - - return false; -} - -/// ActOnDependentIdExpression - Handle a dependent declaration name -/// that was just parsed. +/// ActOnDependentIdExpression - Handle a dependent id-expression that +/// was just parsed. This is only possible with an explicit scope +/// specifier naming a dependent type. Sema::OwningExprResult Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, DeclarationName Name, SourceLocation NameLoc, - bool CheckForImplicitMember, + bool isAddressOfOperand, const TemplateArgumentListInfo *TemplateArgs) { NestedNameSpecifier *Qualifier = static_cast<NestedNameSpecifier*>(SS.getScopeRep()); - QualType ThisType; - if (CheckForImplicitMember && - IsImplicitDependentMemberReference(*this, Qualifier, ThisType)) { + if (!isAddressOfOperand && + isa<CXXMethodDecl>(CurContext) && + cast<CXXMethodDecl>(CurContext)->isInstance()) { + QualType ThisType = cast<CXXMethodDecl>(CurContext)->getThisType(Context); + // Since the 'this' expression is synthesized, we don't need to // perform the double-lookup check. NamedDecl *FirstQualifierInScope = 0; |