diff options
Diffstat (limited to 'lib/Sema')
-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 |
6 files changed, 162 insertions, 36 deletions
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(); } |