diff options
author | Kaelyn Uhrain <rikka@google.com> | 2013-10-19 00:04:52 +0000 |
---|---|---|
committer | Kaelyn Uhrain <rikka@google.com> | 2013-10-19 00:04:52 +0000 |
commit | f7b63e3e18601459d95849e6fbc776b718d12515 (patch) | |
tree | de0e939c8df5c43b8f58654ce056bf4926995b2a | |
parent | 5315a4631b1a0674e9fe5101b5cb9cb9e9280650 (diff) | |
download | bcm5719-llvm-f7b63e3e18601459d95849e6fbc776b718d12515.tar.gz bcm5719-llvm-f7b63e3e18601459d95849e6fbc776b718d12515.zip |
Be smarter about deciding to add a leading '::' to a
NestedNameSpecifier that replaces an existing specifier.
llvm-svn: 193019
-rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 71 | ||||
-rw-r--r-- | clang/test/SemaCXX/qualified-id-lookup.cpp | 4 | ||||
-rw-r--r-- | clang/test/SemaCXX/using-decl-1.cpp | 12 |
3 files changed, 57 insertions, 30 deletions
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 2383b4d25b6..bb1150fc72a 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -3575,6 +3575,7 @@ typedef SmallVector<SpecifierInfo, 16> SpecifierInfoList; class NamespaceSpecifierSet { ASTContext &Context; DeclContextList CurContextChain; + std::string CurNameSpecifier; SmallVector<const IdentifierInfo*, 4> CurContextIdentifiers; SmallVector<const IdentifierInfo*, 4> CurNameSpecifierIdentifiers; bool isSorted; @@ -3594,9 +3595,13 @@ class NamespaceSpecifierSet { CXXScopeSpec *CurScopeSpec) : Context(Context), CurContextChain(BuildContextChain(CurContext)), isSorted(false) { - if (CurScopeSpec && CurScopeSpec->getScopeRep()) - getNestedNameSpecifierIdentifiers(CurScopeSpec->getScopeRep(), - CurNameSpecifierIdentifiers); + if (NestedNameSpecifier *NNS = + CurScopeSpec ? CurScopeSpec->getScopeRep() : 0) { + llvm::raw_string_ostream SpecifierOStream(CurNameSpecifier); + NNS->print(SpecifierOStream, Context.getPrintingPolicy()); + + getNestedNameSpecifierIdentifiers(NNS, CurNameSpecifierIdentifiers); + } // Build the list of identifiers that would be used for an absolute // (from the global context) NestedNameSpecifier referring to the current // context. @@ -3659,6 +3664,25 @@ void NamespaceSpecifierSet::SortNamespaces() { isSorted = true; } +static unsigned BuildNestedNameSpecifier(ASTContext &Context, + DeclContextList &DeclChain, + NestedNameSpecifier *&NNS) { + unsigned NumSpecifiers = 0; + for (DeclContextList::reverse_iterator C = DeclChain.rbegin(), + CEnd = DeclChain.rend(); + C != CEnd; ++C) { + if (NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(*C)) { + NNS = NestedNameSpecifier::Create(Context, NNS, ND); + ++NumSpecifiers; + } else if (RecordDecl *RD = dyn_cast_or_null<RecordDecl>(*C)) { + NNS = NestedNameSpecifier::Create(Context, NNS, RD->isTemplateDecl(), + RD->getTypeForDecl()); + ++NumSpecifiers; + } + } + return NumSpecifiers; +} + void NamespaceSpecifierSet::AddNameSpecifier(DeclContext *Ctx) { NestedNameSpecifier *NNS = NULL; unsigned NumSpecifiers = 0; @@ -3673,34 +3697,37 @@ void NamespaceSpecifierSet::AddNameSpecifier(DeclContext *Ctx) { NamespaceDeclChain.pop_back(); } + // Build the NestedNameSpecifier from what is left of the NamespaceDeclChain + NumSpecifiers = BuildNestedNameSpecifier(Context, NamespaceDeclChain, NNS); + // Add an explicit leading '::' specifier if needed. if (NamespaceDeclChain.empty()) { - NamespaceDeclChain = FullNamespaceDeclChain; + // Rebuild the NestedNameSpecifier as a globally-qualified specifier. NNS = NestedNameSpecifier::GlobalSpecifier(Context); + NumSpecifiers = + BuildNestedNameSpecifier(Context, FullNamespaceDeclChain, NNS); } else if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(NamespaceDeclChain.back())) { IdentifierInfo *Name = ND->getIdentifier(); - if (std::find(CurContextIdentifiers.begin(), CurContextIdentifiers.end(), - Name) != CurContextIdentifiers.end() || - std::find(CurNameSpecifierIdentifiers.begin(), + bool SameNameSpecifier = false; + if (std::find(CurNameSpecifierIdentifiers.begin(), CurNameSpecifierIdentifiers.end(), Name) != CurNameSpecifierIdentifiers.end()) { - NamespaceDeclChain = FullNamespaceDeclChain; - NNS = NestedNameSpecifier::GlobalSpecifier(Context); + std::string NewNameSpecifier; + llvm::raw_string_ostream SpecifierOStream(NewNameSpecifier); + SmallVector<const IdentifierInfo *, 4> NewNameSpecifierIdentifiers; + getNestedNameSpecifierIdentifiers(NNS, NewNameSpecifierIdentifiers); + NNS->print(SpecifierOStream, Context.getPrintingPolicy()); + SpecifierOStream.flush(); + SameNameSpecifier = NewNameSpecifier == CurNameSpecifier; } - } - - // Build the NestedNameSpecifier from what is left of the NamespaceDeclChain - for (DeclContextList::reverse_iterator C = NamespaceDeclChain.rbegin(), - CEnd = NamespaceDeclChain.rend(); - C != CEnd; ++C) { - if (NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(*C)) { - NNS = NestedNameSpecifier::Create(Context, NNS, ND); - ++NumSpecifiers; - } else if (RecordDecl *RD = dyn_cast_or_null<RecordDecl>(*C)) { - NNS = NestedNameSpecifier::Create(Context, NNS, RD->isTemplateDecl(), - RD->getTypeForDecl()); - ++NumSpecifiers; + if (SameNameSpecifier || + std::find(CurContextIdentifiers.begin(), CurContextIdentifiers.end(), + Name) != CurContextIdentifiers.end()) { + // Rebuild the NestedNameSpecifier as a globally-qualified specifier. + NNS = NestedNameSpecifier::GlobalSpecifier(Context); + NumSpecifiers = + BuildNestedNameSpecifier(Context, FullNamespaceDeclChain, NNS); } } diff --git a/clang/test/SemaCXX/qualified-id-lookup.cpp b/clang/test/SemaCXX/qualified-id-lookup.cpp index 26f1d7c472f..23164fa42f3 100644 --- a/clang/test/SemaCXX/qualified-id-lookup.cpp +++ b/clang/test/SemaCXX/qualified-id-lookup.cpp @@ -86,13 +86,13 @@ namespace a { namespace a { namespace a { // A1 namespace a { // A2 - int i; // expected-note{{'::a::a::a::i' declared here}} + int i; // expected-note{{'a::a::a::i' declared here}} } } } void test_a() { - a::a::i = 3; // expected-error{{no member named 'i' in namespace 'a::a'; did you mean '::a::a::a::i'?}} + a::a::i = 3; // expected-error{{no member named 'i' in namespace 'a::a'; did you mean 'a::a::a::i'?}} a::a::a::i = 4; a::a::j = 3; // expected-error-re{{no member named 'j' in namespace 'a::a'$}} } diff --git a/clang/test/SemaCXX/using-decl-1.cpp b/clang/test/SemaCXX/using-decl-1.cpp index 41710cc9090..24d92f175c3 100644 --- a/clang/test/SemaCXX/using-decl-1.cpp +++ b/clang/test/SemaCXX/using-decl-1.cpp @@ -139,24 +139,24 @@ using typename N::FFG; // expected-error {{no member named 'FFG' in namespace 'u // Currently hints aren't provided to drop out the incorrect M::. namespace using_suggestion_ty_dropped_nested_specifier { namespace N { -class AAA {}; +class AAA {}; // expected-note {{'N::AAA' declared here}} namespace M { } } -using N::M::AAA; // expected-error {{no member named 'AAA' in namespace 'using_suggestion_ty_dropped_nested_specifier::N::M'}} +using N::M::AAA; // expected-error {{no member named 'AAA' in namespace 'using_suggestion_ty_dropped_nested_specifier::N::M'; did you mean 'N::AAA'?}} } namespace using_suggestion_tyname_ty_dropped_nested_specifier { namespace N { -class AAA {}; +class AAA {}; // expected-note {{'N::AAA' declared here}} namespace M { } } -using typename N::M::AAA; // expected-error {{no member named 'AAA' in namespace 'using_suggestion_tyname_ty_dropped_nested_specifier::N::M'}} +using typename N::M::AAA; // expected-error {{no member named 'AAA' in namespace 'using_suggestion_tyname_ty_dropped_nested_specifier::N::M'; did you mean 'N::AAA'?}} } namespace using_suggestion_val_dropped_nested_specifier { namespace N { -void FFF() {} +void FFF() {} // expected-note {{'N::FFF' declared here}} namespace M { } } -using N::M::FFF; // expected-error {{no member named 'FFF' in namespace 'using_suggestion_val_dropped_nested_specifier::N::M'}} +using N::M::FFF; // expected-error {{no member named 'FFF' in namespace 'using_suggestion_val_dropped_nested_specifier::N::M'; did you mean 'N::FFF'?}} } |