diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-04-01 21:51:26 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-04-01 21:51:26 +0000 |
commit | 31a19b6989bbf326d2de5ae12e712e2a65ca9c34 (patch) | |
tree | e79ad32f23a5f590558c274cf11b000f10b04042 | |
parent | faa435a326a694e0517d035376e616ff82655fe5 (diff) |
Make parsing a semantic analysis a little more robust following Sema
failures that involve malformed types, e.g., "typename X::foo" where
"foo" isn't a type, or "std::vector<void>" that doens't instantiate
properly.
Similarly, be a bit smarter in our handling of ambiguities that occur
in Sema::getTypeName, to eliminate duplicate error messages about
ambiguous name lookup.
This eliminates two XFAILs in test/SemaCXX, one of which was crying
out to us, trying to tell us that we were producing repeated error
messages.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68251 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Parse/Parser.h | 6 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 26 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 24 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 20 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 17 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 17 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 4 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 31 | ||||
-rw-r--r-- | lib/Sema/SemaInherit.cpp | 28 | ||||
-rw-r--r-- | lib/Sema/SemaInherit.h | 16 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 112 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 7 | ||||
-rw-r--r-- | test/SemaCXX/member-name-lookup.cpp | 34 | ||||
-rw-r--r-- | test/SemaCXX/using-directive.cpp | 14 | ||||
-rw-r--r-- | test/SemaTemplate/nested-name-spec-template.cpp | 2 |
15 files changed, 241 insertions, 117 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 86bda4551a..3969cf4765 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1005,8 +1005,8 @@ private: //===--------------------------------------------------------------------===// // C++ 9: classes [class] and C structs/unions. - TypeTy *ParseClassName(SourceLocation &EndLocation, - const CXXScopeSpec *SS = 0); + TypeResult ParseClassName(SourceLocation &EndLocation, + const CXXScopeSpec *SS = 0); void ParseClassSpecifier(DeclSpec &DS, TemplateParameterLists *TemplateParams = 0, AccessSpecifier AS = AS_none); @@ -1065,7 +1065,7 @@ private: const CXXScopeSpec *SS, SourceLocation TemplateKWLoc = SourceLocation(), bool AllowTypeAnnotation = true); - bool AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0); + void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0); bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs, TemplateArgIsTypeList &TemplateArgIsType, TemplateArgLocationList &TemplateArgLocations); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 11658d4c50..e233a22162 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -558,8 +558,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, } case tok::annot_typename: { - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, - Tok.getAnnotationValue()); + if (Tok.getAnnotationValue()) + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, + Tok.getAnnotationValue()); + else + DS.SetTypeSpecError(); DS.SetRangeEnd(Tok.getAnnotationEndLoc()); ConsumeToken(); // The typename @@ -648,9 +651,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // Turn the template-id annotation token into a type annotation // token, then try again to parse it as a type-specifier. - if (AnnotateTemplateIdTokenAsType()) - DS.SetTypeSpecError(); - + AnnotateTemplateIdTokenAsType(); continue; } @@ -915,8 +916,11 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid, // simple-type-specifier: case tok::annot_typename: { - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, - Tok.getAnnotationValue()); + if (Tok.getAnnotationValue()) + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, + Tok.getAnnotationValue()); + else + DS.SetTypeSpecError(); DS.SetRangeEnd(Tok.getAnnotationEndLoc()); ConsumeToken(); // The typename @@ -1893,11 +1897,11 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // FIXME: Inaccurate. SourceLocation NameLoc = Tok.getLocation(); SourceLocation EndLoc; - if (TypeTy *Type = ParseClassName(EndLoc)) { - D.setDestructor(Type, TildeLoc, NameLoc); - } else { + TypeResult Type = ParseClassName(EndLoc); + if (Type.isInvalid()) D.SetIdentifier(0, TildeLoc); - } + else + D.setDestructor(Type.get(), TildeLoc, NameLoc); } else { Diag(Tok, diag::err_expected_class_name); D.SetIdentifier(0, TildeLoc); diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 663fea5096..1cf4a8fe5f 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -301,21 +301,23 @@ Parser::DeclPtrTy Parser::ParseStaticAssertDeclaration() { /// identifier /// simple-template-id /// -Parser::TypeTy *Parser::ParseClassName(SourceLocation &EndLocation, - const CXXScopeSpec *SS) { +Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation, + const CXXScopeSpec *SS) { // Check whether we have a template-id that names a type. if (Tok.is(tok::annot_template_id)) { TemplateIdAnnotation *TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); if (TemplateId->Kind == TNK_Type_template) { - if (AnnotateTemplateIdTokenAsType(SS)) - return 0; + AnnotateTemplateIdTokenAsType(SS); assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); TypeTy *Type = Tok.getAnnotationValue(); EndLocation = Tok.getAnnotationEndLoc(); ConsumeToken(); - return Type; + + if (Type) + return Type; + return true; } // Fall through to produce an error below. @@ -323,7 +325,7 @@ Parser::TypeTy *Parser::ParseClassName(SourceLocation &EndLocation, if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_class_name); - return 0; + return true; } // We have an identifier; check whether it is actually a type. @@ -331,7 +333,7 @@ Parser::TypeTy *Parser::ParseClassName(SourceLocation &EndLocation, Tok.getLocation(), CurScope, SS); if (!Type) { Diag(Tok, diag::err_expected_class_name); - return 0; + return true; } // Consume the identifier. @@ -592,7 +594,7 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) { if (IsVirtual) { // Complain about duplicate 'virtual' Diag(VirtualLoc, diag::err_dup_virtual) - << SourceRange(VirtualLoc, VirtualLoc); + << CodeModificationHint::CreateRemoval(SourceRange(VirtualLoc)); } IsVirtual = true; @@ -607,8 +609,8 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) { // Parse the class-name. SourceLocation EndLocation; - TypeTy *BaseType = ParseClassName(EndLocation, &SS); - if (!BaseType) + TypeResult BaseType = ParseClassName(EndLocation, &SS); + if (BaseType.isInvalid()) return true; // Find the complete source range for the base-specifier. @@ -617,7 +619,7 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) { // Notify semantic analysis that we have parsed a complete // base-specifier. return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access, - BaseType, BaseLoc); + BaseType.get(), BaseLoc); } /// getAccessSpecifierIfPresent - Determine whether the next token is diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 2c6963a05f..5865771f60 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -148,12 +148,11 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) { if (TemplateId->Kind == TNK_Type_template || TemplateId->Kind == TNK_Dependent_template_name) { - if (AnnotateTemplateIdTokenAsType(&SS)) - SS.clear(); + AnnotateTemplateIdTokenAsType(&SS); + SS.clear(); assert(Tok.is(tok::annot_typename) && "AnnotateTemplateIdTokenAsType isn't working"); - Token TypeToken = Tok; ConsumeToken(); assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!"); @@ -163,12 +162,15 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) { SS.setBeginLoc(TypeToken.getLocation()); HasScopeSpecifier = true; } - - SS.setScopeRep( - Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, - TypeToken.getAnnotationValue(), - TypeToken.getAnnotationRange(), - CCLoc)); + + if (TypeToken.getAnnotationValue()) + SS.setScopeRep( + Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, + TypeToken.getAnnotationValue(), + TypeToken.getAnnotationRange(), + CCLoc)); + else + SS.setScopeRep(0); SS.setEndLoc(CCLoc); continue; } else diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 45d148e38b..0f9bcd2219 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -588,8 +588,10 @@ void Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, /// \brief Replaces a template-id annotation token with a type /// annotation token. /// -/// \returns true if there was an error, false otherwise. -bool Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) { +/// If there was a failure when forming the type from the template-id, +/// a type annotation token will still be created, but will have a +/// NULL type pointer to signify an error. +void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) { assert(Tok.is(tok::annot_template_id) && "Requires template-id tokens"); TemplateIdAnnotation *TemplateId @@ -610,16 +612,9 @@ bool Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) { TemplateArgsPtr, TemplateId->getTemplateArgLocations(), TemplateId->RAngleLoc); - if (Type.isInvalid()) { - // FIXME: better recovery? - ConsumeToken(); - TemplateId->Destroy(); - return true; - } - // Create the new "type" annotation token. Tok.setKind(tok::annot_typename); - Tok.setAnnotationValue(Type.get()); + Tok.setAnnotationValue(Type.isInvalid()? 0 : Type.get()); if (SS && SS->isNotEmpty()) // it was a C++ qualified type name. Tok.setLocation(SS->getBeginLoc()); @@ -629,8 +624,6 @@ bool Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) { // class template specialization again. PP.ReplaceLastTokenWithAnnotation(Tok); TemplateId->Destroy(); - - return false; } /// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]). diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 17eca37ef3..8903da29a0 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -851,22 +851,22 @@ bool Parser::TryAnnotateTypeOrScopeToken() { return false; } - if (AnnotateTemplateIdTokenAsType(0)) - return false; - + AnnotateTemplateIdTokenAsType(0); assert(Tok.is(tok::annot_typename) && "AnnotateTemplateIdTokenAsType isn't working properly"); - Ty = Actions.ActOnTypenameType(TypenameLoc, SS, SourceLocation(), - Tok.getAnnotationValue()); + if (Tok.getAnnotationValue()) + Ty = Actions.ActOnTypenameType(TypenameLoc, SS, SourceLocation(), + Tok.getAnnotationValue()); + else + Ty = true; } else { Diag(Tok, diag::err_expected_type_name_after_typename) << SS.getRange(); return false; } - // FIXME: better error recovery! Tok.setKind(tok::annot_typename); - Tok.setAnnotationValue(Ty.get()); + Tok.setAnnotationValue(Ty.isInvalid()? 0 : Ty.get()); Tok.setAnnotationEndLoc(Tok.getLocation()); Tok.setLocation(TypenameLoc); PP.AnnotateCachedTokens(Tok); @@ -925,7 +925,8 @@ bool Parser::TryAnnotateTypeOrScopeToken() { // template-id annotation in a context where we weren't allowed // to produce a type annotation token. Update the template-id // annotation token to a type annotation token now. - return !AnnotateTemplateIdTokenAsType(&SS); + AnnotateTemplateIdTokenAsType(&SS); + return true; } } diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 7f686369a8..c442b84669 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -755,7 +755,6 @@ public: /// pointers used to reconstruct new'ed Decl*[] array containing /// found ambiguous decls. LookupResult is owner of this array. AmbiguousLookupStoresDecls - } StoredKind; /// The first lookup result, whose contents depend on the kind of @@ -939,6 +938,9 @@ public: iterator begin(); iterator end(); + + /// \brief Free the memory associated with this lookup. + void Destroy(); }; private: diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 584d2b11f9..e02e2ee876 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -80,9 +80,34 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, case LookupResult::AmbiguousBaseSubobjectTypes: case LookupResult::AmbiguousBaseSubobjects: - case LookupResult::AmbiguousReference: + case LookupResult::AmbiguousReference: { + // Look to see if we have a type anywhere in the list of results. + for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end(); + Res != ResEnd; ++Res) { + if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res)) { + IIDecl = *Res; + break; + } + } + + if (!IIDecl) { + // None of the entities we found is a type, so there is no way + // to even assume that the result is a type. In this case, don't + // complain about the ambiguity. The parser will either try to + // perform this lookup again (e.g., as an object name), which + // will produce the ambiguity, or will complain that it expected + // a type name. + Result.Destroy(); + return 0; + } + + // We found a type within the ambiguous lookup; diagnose the + // ambiguity and then return that type. This might be the right + // answer, or it might not be, but it suppresses any attempt to + // perform the name lookup again. DiagnoseAmbiguousLookup(Result, DeclarationName(&II), NameLoc); - return 0; + break; + } case LookupResult::Found: IIDecl = Result.getAsDecl(); @@ -3153,7 +3178,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, // // struct S s; // - // causes needless err_ovl_no_viable_function_in_init latter. + // causes needless "incomplete type" error later. Name = 0; PrevDecl = 0; Invalid = true; diff --git a/lib/Sema/SemaInherit.cpp b/lib/Sema/SemaInherit.cpp index cc495c5ea4..c01430c9ee 100644 --- a/lib/Sema/SemaInherit.cpp +++ b/lib/Sema/SemaInherit.cpp @@ -25,6 +25,34 @@ using namespace clang; +/// \brief Computes the set of declarations referenced by these base +/// paths. +void BasePaths::ComputeDeclsFound() { + assert(NumDeclsFound == 0 && !DeclsFound && + "Already computed the set of declarations"); + + std::set<NamedDecl *> Decls; + for (BasePaths::paths_iterator Path = begin(), PathEnd = end(); + Path != PathEnd; ++Path) + Decls.insert(*Path->Decls.first); + + NumDeclsFound = Decls.size(); + DeclsFound = new NamedDecl * [NumDeclsFound]; + std::copy(Decls.begin(), Decls.end(), DeclsFound); +} + +NamedDecl **BasePaths::found_decls_begin() { + if (NumDeclsFound == 0) + ComputeDeclsFound(); + return DeclsFound; +} + +NamedDecl **BasePaths::found_decls_end() { + if (NumDeclsFound == 0) + ComputeDeclsFound(); + return DeclsFound + NumDeclsFound; +} + /// isAmbiguous - Determines whether the set of paths provided is /// ambiguous, i.e., there are two or more paths that refer to /// different base class subobjects of the same type. BaseType must be diff --git a/lib/Sema/SemaInherit.h b/lib/Sema/SemaInherit.h index 6138685b26..20c8ae5e03 100644 --- a/lib/Sema/SemaInherit.h +++ b/lib/Sema/SemaInherit.h @@ -132,8 +132,16 @@ namespace clang { /// DetectedVirtual - The base class that is virtual. const RecordType *DetectedVirtual; + /// \brief Array of the declarations that have been found. This + /// array is constructed only if needed, e.g., to iterate over the + /// results within LookupResult. + NamedDecl **DeclsFound; + unsigned NumDeclsFound; + friend class Sema; + void ComputeDeclsFound(); + public: typedef std::list<BasePath>::const_iterator paths_iterator; @@ -143,15 +151,21 @@ namespace clang { bool RecordPaths = true, bool DetectVirtual = true) : FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths), - DetectVirtual(DetectVirtual), DetectedVirtual(0) + DetectVirtual(DetectVirtual), DetectedVirtual(0), DeclsFound(0), + NumDeclsFound(0) {} + ~BasePaths() { delete [] DeclsFound; } + paths_iterator begin() const { return Paths.begin(); } paths_iterator end() const { return Paths.end(); } BasePath& front() { return Paths.front(); } const BasePath& front() const { return Paths.front(); } + NamedDecl **found_decls_begin(); + NamedDecl **found_decls_end(); + bool isAmbiguous(QualType BaseType); /// isFindingAmbiguities - Whether we are finding multiple paths diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 69bd5602d3..d85123c853 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -437,13 +437,16 @@ Sema::LookupResult::iterator::operator*() const { case OverloadedDeclFromIdResolver: return *IdentifierResolver::iterator::getFromOpaqueValue(Current); + case AmbiguousLookupStoresBasePaths: + if (Result->Last) + return *reinterpret_cast<NamedDecl**>(Current); + + // Fall through to handle the DeclContext::lookup_iterator we're + // storing. + case OverloadedDeclFromDeclContext: - return *reinterpret_cast<DeclContext::lookup_iterator>(Current); - case AmbiguousLookupStoresDecls: - case AmbiguousLookupStoresBasePaths: - assert(false && "Cannot look into ambiguous lookup results"); - break; + return *reinterpret_cast<DeclContext::lookup_iterator>(Current); } return 0; @@ -470,39 +473,90 @@ Sema::LookupResult::iterator& Sema::LookupResult::iterator::operator++() { break; } - case OverloadedDeclFromDeclContext: { + case AmbiguousLookupStoresBasePaths: + if (Result->Last) { + NamedDecl ** I = reinterpret_cast<NamedDecl**>(Current); + ++I; + Current = reinterpret_cast<uintptr_t>(I); + break; + } + // Fall through to handle the DeclContext::lookup_iterator we're + // storing. + + case OverloadedDeclFromDeclContext: + case AmbiguousLookupStoresDecls: { DeclContext::lookup_iterator I = reinterpret_cast<DeclContext::lookup_iterator>(Current); ++I; Current = reinterpret_cast<uintptr_t>(I); break; } - - case AmbiguousLookupStoresDecls: - case AmbiguousLookupStoresBasePaths: - assert(false && "Cannot look into ambiguous lookup results"); - break; } return *this; } Sema::LookupResult::iterator Sema::LookupResult::begin() { - assert(!isAmbiguous() && "Lookup into an ambiguous result"); - if (StoredKind != OverloadedDeclSingleDecl) + switch (StoredKind) { + case SingleDecl: + case OverloadedDeclFromIdResolver: + case OverloadedDeclFromDeclContext: + case AmbiguousLookupStoresDecls: return iterator(this, First); - OverloadedFunctionDecl * Ovl = - reinterpret_cast<OverloadedFunctionDecl*>(First); - return iterator(this, reinterpret_cast<uintptr_t>(&(*Ovl->function_begin()))); + + case OverloadedDeclSingleDecl: { + OverloadedFunctionDecl * Ovl = + reinterpret_cast<OverloadedFunctionDecl*>(First); + return iterator(this, + reinterpret_cast<uintptr_t>(&(*Ovl->function_begin()))); + } + + case AmbiguousLookupStoresBasePaths: + if (Last) + return iterator(this, + reinterpret_cast<uintptr_t>(getBasePaths()->found_decls_begin())); + else + return iterator(this, + reinterpret_cast<uintptr_t>(getBasePaths()->front().Decls.first)); + } + + // Required to suppress GCC warning. + return iterator(); } Sema::LookupResult::iterator Sema::LookupResult::end() { - assert(!isAmbiguous() && "Lookup into an ambiguous result"); - if (StoredKind != OverloadedDeclSingleDecl) + switch (StoredKind) { + case SingleDecl: + case OverloadedDeclFromIdResolver: + case OverloadedDeclFromDeclContext: + case AmbiguousLookupStoresDecls: return iterator(this, Last); - OverloadedFunctionDecl * Ovl = - reinterpret_cast<OverloadedFunctionDecl*>(First); - return iterator(this, reinterpret_cast<uintptr_t>(&(*Ovl->function_end()))); + + case OverloadedDeclSingleDecl: { + OverloadedFunctionDecl * Ovl = + reinterpret_cast<OverloadedFunctionDecl*>(First); + return iterator(this, + reinterpret_cast<uintptr_t>(&(*Ovl->function_end()))); + } + + case AmbiguousLookupStoresBasePaths: + if (Last) + return iterator(this, + reinterpret_cast<uintptr_t>(getBasePaths()->found_decls_end())); + else + return iterator(this, reinterpret_cast<uintptr_t>( + getBasePaths()->front().Decls.second)); + } + + // Required to suppress GCC warning. + return iterator(); +} + +void Sema::LookupResult::Destroy() { + if (BasePaths *Paths = getBasePaths()) + delete Paths; + else if (getKind() == AmbiguousReference) + delete[] reinterpret_cast<NamedDecl **>(First); } static void @@ -1071,8 +1125,7 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name, SourceRange LookupRange) { assert(Result.isAmbiguous() && "Lookup result must be ambiguous"); - if (BasePaths *Paths = Result.getBasePaths()) - { + if (BasePaths *Paths = Result.getBasePaths()) { if (Result.getKind() == LookupResult::AmbiguousBaseSubobjects) { QualType SubobjectType = Paths->front().back().Base->getType(); Diag(NameLoc, diag::err_ambiguous_member_multiple_subobjects) @@ -1080,11 +1133,13 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name, << LookupRange; DeclContext::lookup_iterator Found = Paths->front().Decls.first; - while (isa<CXXMethodDecl>(*Found) && cast<CXXMethodDecl>(*Found)->isStatic()) + while (isa<CXXMethodDecl>(*Found) && + cast<CXXMethodDecl>(*Found)->isStatic()) ++Found; Diag((*Found)->getLocation(), diag::note_ambiguous_member_found); + Result.Destroy(); return true; } @@ -1102,20 +1157,18 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name, Diag(D->getLocation(), diag::note_ambiguous_member_found); } - delete Paths; + Result.Destroy(); return true; } else if (Result.getKind() == LookupResult::AmbiguousReference) { - Diag(NameLoc, diag::err_ambiguous_reference) << Name << LookupRange; NamedDecl **DI = reinterpret_cast<NamedDecl **>(Result.First), - **DEnd = reinterpret_cast<NamedDecl **>(Result.Last); + **DEnd = reinterpret_cast<NamedDecl **>(Result.Last); for (; DI != DEnd; ++DI) Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) << *DI; - delete[] reinterpret_cast<NamedDecl **>(Result.First); - + Result.Destroy(); return true; } @@ -1466,7 +1519,6 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, AssociatedNamespaces, AssociatedClasses); // C++ [basic.lookup.argdep]p3: - // // Let X be the lookup set produced by unqualified lookup (3.4.1) // and let Y be the lookup set produced by argument dependent // lookup (defined as follows). If X contains [...] then Y is diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 5db19a59ac..abc3ac08e9 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -870,8 +870,11 @@ Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc, QualType Result = CheckTemplateIdType(Template, TemplateLoc, LAngleLoc, &TemplateArgs[0], TemplateArgs.size(), RAngleLoc); - TemplateArgsIn.release(); + + if (Result.isNull()) + return true; + return Result.getAsOpaquePtr(); } @@ -2102,6 +2105,8 @@ Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, return true; QualType T = CheckTypenameType(NNS, II, SourceRange(TypenameLoc, IdLoc)); + if (T.isNull()) + return true; return T.getAsOpaquePtr(); } diff --git a/test/SemaCXX/member-name-lookup.cpp b/test/SemaCXX/member-name-lookup.cpp index 871bc99456..9fcd922ddf 100644 --- a/test/SemaCXX/member-name-lookup.cpp +++ b/test/SemaCXX/member-name-lookup.cpp @@ -1,36 +1,33 @@ // RUN: clang-cc -fsyntax-only -verify %s -// XFAIL -// fails due to exact diagnostic matching - struct A { - int a; // expected-note{{member found by ambiguous name lookup}} + int a; // expected-note 4{{member found by ambiguous name lookup}} static int b; - static int c; // expected-note{{member found by ambiguous name lookup}} + static int c; // expected-note 4{{member found by ambiguous name lookup}} enum E { enumerator }; typedef int type; static void f(int); - void f(float); // expected-note{{member found by ambiguous name lookup}} + void f(float); // expected-note 2{{member found by ambiguous name lookup}} static void static_f(int); static void static_f(double); }; struct B : A { - int d; // expected-note{{member found by ambiguous name lookup}} + int d; // expected-note 2{{member found by ambiguous name lookup}} enum E2 { enumerator2 }; - enum E3 { enumerator3 }; // expected-note{{member found by ambiguous name lookup}} + enum E3 { enumerator3 }; // expected-note 2{{member found by ambiguous name lookup}} }; struct C : A { - int c; // expected-note{{member found by ambiguous name lookup}} - int d; // expected-note{{member found by ambiguous name lookup}} + int c; // expected-note 2{{member found by ambiguous name lookup}} + int d; // expected-note 2{{member found by ambiguous name lookup}} - enum E3 { enumerator3_2 }; // expected-note{{member found by ambiguous name lookup}} + enum E3 { enumerator3_2 }; // expected-note 2{{member found by ambiguous name lookup}} }; struct D : B, C { @@ -50,7 +47,7 @@ void test_lookup(D d) { D::E2 e2 = D::enumerator2; // okay - D::E3 e3; // expected-error{{member 'E3' found in multiple base classes of different types}} + D::E3 e3; // expected-error{{multiple base classes}} } void D::test_lookup() { @@ -70,18 +67,18 @@ void D::test_lookup() { } struct B2 : virtual A { - int d; // expected-note{{member found by ambiguous name lookup}} + int d; // expected-note 2{{member found by ambiguous name lookup}} enum E2 { enumerator2 }; - enum E3 { enumerator3 }; // expected-note{{member found by ambiguous name lookup}} + enum E3 { enumerator3 }; // expected-note 2 {{member found by ambiguous name lookup}} }; struct C2 : virtual A { - int c; // expected-note{{member found by ambiguous name lookup}} - int d; // expected-note{{member found by ambiguous name lookup}} + int c; // expected-note 2{{member found by ambiguous name lookup}} + int d; // expected-note 2{{member found by ambiguous name lookup}} - enum E3 { enumerator3_2 }; // expected-note{{member found by ambiguous name lookup}} + enum E3 { enumerator3_2 }; // expected-note 2{{member found by ambiguous name lookup}} }; struct D2 : B2, C2 { @@ -147,6 +144,5 @@ struct HasAnotherMemberType : HasMemberType1, HasMemberType2 { }; struct UsesAmbigMemberType : HasMemberType1, HasMemberType2 { - type t; // expected-error{{member 'type' found in multiple base classes of different types}} \ - // expected-error{{expected ';' at end of declaration list}} + type t; // expected-error{{member 'type' found in multiple base classes of different types}} }; diff --git a/test/SemaCXX/using-directive.cpp b/test/SemaCXX/using-directive.cpp index 767b49b76f..324052f190 100644 --- a/test/SemaCXX/using-directive.cpp +++ b/test/SemaCXX/using-directive.cpp @@ -1,9 +1,7 @@ // RUN: clang-cc -fsyntax-only -verify %s -// XFAIL -// fails due to exact diagnostic matching namespace A { - short i; // expected-note{{candidate found by name lookup is 'A::i'}} + short i; // expected-note 2{{candidate found by name lookup is 'A::i'}} namespace B { long i; // expected-note{{candidate found by name lookup is 'A::B::i'}} void f() {} // expected-note{{candidate function}} @@ -58,7 +56,7 @@ void K1::foo() {} // okay // FIXME: Do we want err_ovl_no_viable_function_in_init here? struct K2 k2; // expected-error{{reference to 'K2' is ambiguous}} \ - expected-error{{no matching constructor}} + expected-error{{incomplete type}} // FIXME: This case is incorrectly diagnosed! //K2 k3; @@ -66,7 +64,7 @@ struct K2 k2; // expected-error{{reference to 'K2' is ambiguous}} \ class X { // expected-note{{candidate found by name lookup is 'X'}} // FIXME: produce a suitable error message for this - using namespace A; // expected-error{{expected unqualified-id}} + using namespace A; // expected-error{{expected member name or}} }; namespace N { @@ -96,7 +94,8 @@ namespace OneFunction { } namespace TwoTag { - struct X; // expected-note{{candidate found by name lookup is 'TwoTag::X'}} + struct X; // expected-note{{candidate found by name lookup is 'TwoTag::X'}} \ + // expected-note{{forward declaration}} } namespace FuncHidesTagAmbiguity { @@ -105,6 +104,7 @@ namespace FuncHidesTagAmbiguity { using namespace TwoTag; void test() { - (void)X(); // expected-error{{reference to 'X' is ambiguous}} + (void)X(); // expected-error{{reference to 'X' is ambiguous}} \ + // FIXME: expected-error{{invalid use of incomplete type}} } } diff --git a/test/SemaTemplate/nested-name-spec-template.cpp b/test/SemaTemplate/nested-name-spec-template.cpp index 6df2ca6a91..7805040048 100644 --- a/test/SemaTemplate/nested-name-spec-template.cpp +++ b/test/SemaTemplate/nested-name-spec-template.cpp @@ -52,7 +52,7 @@ struct ::N::A<int>::X { #if 0 // FIXME: the following crashes the parser, because Sema has no way to -// community that the "dependent" template-name N::template B doesn't +// communicate that the "dependent" template-name N::template B doesn't // actually refer to a template. template<typename T> struct TestA { |