| Cedric Venet | 08438133 | 2009-02-14 20:20:19 +0000 | [diff] [blame] | 1 | //===--- SemaCXXScopeSpec.cpp - Semantic Analysis for C++ scope specifiers-===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | // This file implements C++ semantic analysis for scope specifiers. | 
|  | 11 | // | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 |  | 
| John McCall | 8302463 | 2010-08-25 22:03:47 +0000 | [diff] [blame] | 14 | #include "clang/Sema/SemaInternal.h" | 
| Douglas Gregor | c3a6ade | 2010-08-12 20:07:10 +0000 | [diff] [blame] | 15 | #include "clang/Sema/Lookup.h" | 
| Cedric Venet | 08438133 | 2009-02-14 20:20:19 +0000 | [diff] [blame] | 16 | #include "clang/AST/ASTContext.h" | 
| Douglas Gregor | c9f9b86 | 2009-05-11 19:58:34 +0000 | [diff] [blame] | 17 | #include "clang/AST/DeclTemplate.h" | 
| Douglas Gregor | d806156 | 2009-08-06 03:17:00 +0000 | [diff] [blame] | 18 | #include "clang/AST/ExprCXX.h" | 
| Douglas Gregor | 5253768 | 2009-03-19 00:18:19 +0000 | [diff] [blame] | 19 | #include "clang/AST/NestedNameSpecifier.h" | 
| Anders Carlsson | d624e16 | 2009-08-26 23:45:07 +0000 | [diff] [blame] | 20 | #include "clang/Basic/PartialDiagnostic.h" | 
| John McCall | 8b0666c | 2010-08-20 18:27:03 +0000 | [diff] [blame] | 21 | #include "clang/Sema/DeclSpec.h" | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 22 | #include "TypeLocBuilder.h" | 
| Cedric Venet | 08438133 | 2009-02-14 20:20:19 +0000 | [diff] [blame] | 23 | #include "llvm/ADT/STLExtras.h" | 
| Douglas Gregor | 168190d | 2009-07-22 00:28:09 +0000 | [diff] [blame] | 24 | #include "llvm/Support/raw_ostream.h" | 
| Cedric Venet | 08438133 | 2009-02-14 20:20:19 +0000 | [diff] [blame] | 25 | using namespace clang; | 
|  | 26 |  | 
| Douglas Gregor | 4112718 | 2009-11-04 22:49:18 +0000 | [diff] [blame] | 27 | /// \brief Find the current instantiation that associated with the given type. | 
| Douglas Gregor | bf2b26d | 2011-02-19 19:24:40 +0000 | [diff] [blame] | 28 | static CXXRecordDecl *getCurrentInstantiationOf(QualType T, | 
|  | 29 | DeclContext *CurContext) { | 
| Douglas Gregor | 4112718 | 2009-11-04 22:49:18 +0000 | [diff] [blame] | 30 | if (T.isNull()) | 
|  | 31 | return 0; | 
| John McCall | 2408e32 | 2010-04-27 00:57:59 +0000 | [diff] [blame] | 32 |  | 
|  | 33 | const Type *Ty = T->getCanonicalTypeInternal().getTypePtr(); | 
| Douglas Gregor | bf2b26d | 2011-02-19 19:24:40 +0000 | [diff] [blame] | 34 | if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) { | 
|  | 35 | CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl()); | 
|  | 36 | if (!T->isDependentType()) | 
|  | 37 | return Record; | 
|  | 38 |  | 
|  | 39 | // This may be a member of a class template or class template partial | 
|  | 40 | // specialization. If it's part of the current semantic context, then it's | 
|  | 41 | // an injected-class-name; | 
|  | 42 | for (; !CurContext->isFileContext(); CurContext = CurContext->getParent()) | 
|  | 43 | if (CurContext->Equals(Record)) | 
|  | 44 | return Record; | 
|  | 45 |  | 
|  | 46 | return 0; | 
|  | 47 | } else if (isa<InjectedClassNameType>(Ty)) | 
| John McCall | 2408e32 | 2010-04-27 00:57:59 +0000 | [diff] [blame] | 48 | return cast<InjectedClassNameType>(Ty)->getDecl(); | 
|  | 49 | else | 
|  | 50 | return 0; | 
| Douglas Gregor | 4112718 | 2009-11-04 22:49:18 +0000 | [diff] [blame] | 51 | } | 
|  | 52 |  | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 53 | /// \brief Compute the DeclContext that is associated with the given type. | 
|  | 54 | /// | 
|  | 55 | /// \param T the type for which we are attempting to find a DeclContext. | 
|  | 56 | /// | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 57 | /// \returns the declaration context represented by the type T, | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 58 | /// or NULL if the declaration context cannot be computed (e.g., because it is | 
|  | 59 | /// dependent and not the current instantiation). | 
|  | 60 | DeclContext *Sema::computeDeclContext(QualType T) { | 
| Douglas Gregor | bf2b26d | 2011-02-19 19:24:40 +0000 | [diff] [blame] | 61 | if (!T->isDependentType()) | 
|  | 62 | if (const TagType *Tag = T->getAs<TagType>()) | 
|  | 63 | return Tag->getDecl(); | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 64 |  | 
| Douglas Gregor | bf2b26d | 2011-02-19 19:24:40 +0000 | [diff] [blame] | 65 | return ::getCurrentInstantiationOf(T, CurContext); | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 66 | } | 
|  | 67 |  | 
| Douglas Gregor | 5253768 | 2009-03-19 00:18:19 +0000 | [diff] [blame] | 68 | /// \brief Compute the DeclContext that is associated with the given | 
|  | 69 | /// scope specifier. | 
| Douglas Gregor | d8d297c | 2009-07-21 23:53:31 +0000 | [diff] [blame] | 70 | /// | 
|  | 71 | /// \param SS the C++ scope specifier as it appears in the source | 
|  | 72 | /// | 
|  | 73 | /// \param EnteringContext when true, we will be entering the context of | 
|  | 74 | /// this scope specifier, so we can retrieve the declaration context of a | 
|  | 75 | /// class template or class template partial specialization even if it is | 
|  | 76 | /// not the current instantiation. | 
|  | 77 | /// | 
|  | 78 | /// \returns the declaration context represented by the scope specifier @p SS, | 
|  | 79 | /// or NULL if the declaration context cannot be computed (e.g., because it is | 
|  | 80 | /// dependent and not the current instantiation). | 
|  | 81 | DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, | 
|  | 82 | bool EnteringContext) { | 
| Douglas Gregor | 5253768 | 2009-03-19 00:18:19 +0000 | [diff] [blame] | 83 | if (!SS.isSet() || SS.isInvalid()) | 
| Douglas Gregor | 6bfde49 | 2009-03-18 00:36:05 +0000 | [diff] [blame] | 84 | return 0; | 
| Douglas Gregor | 6bfde49 | 2009-03-18 00:36:05 +0000 | [diff] [blame] | 85 |  | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 86 | NestedNameSpecifier *NNS | 
| Douglas Gregor | c23500e | 2009-03-26 23:56:24 +0000 | [diff] [blame] | 87 | = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); | 
| Douglas Gregor | c9f9b86 | 2009-05-11 19:58:34 +0000 | [diff] [blame] | 88 | if (NNS->isDependent()) { | 
|  | 89 | // If this nested-name-specifier refers to the current | 
|  | 90 | // instantiation, return its DeclContext. | 
|  | 91 | if (CXXRecordDecl *Record = getCurrentInstantiationOf(NNS)) | 
|  | 92 | return Record; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 93 |  | 
| Douglas Gregor | d8d297c | 2009-07-21 23:53:31 +0000 | [diff] [blame] | 94 | if (EnteringContext) { | 
| John McCall | e78aac4 | 2010-03-10 03:28:59 +0000 | [diff] [blame] | 95 | const Type *NNSType = NNS->getAsType(); | 
|  | 96 | if (!NNSType) { | 
|  | 97 | // do nothing, fall out | 
|  | 98 | } else if (const TemplateSpecializationType *SpecType | 
|  | 99 | = NNSType->getAs<TemplateSpecializationType>()) { | 
| Douglas Gregor | e861bac | 2009-08-25 22:51:20 +0000 | [diff] [blame] | 100 | // We are entering the context of the nested name specifier, so try to | 
|  | 101 | // match the nested name specifier to either a primary class template | 
|  | 102 | // or a class template partial specialization. | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 103 | if (ClassTemplateDecl *ClassTemplate | 
| Douglas Gregor | d8d297c | 2009-07-21 23:53:31 +0000 | [diff] [blame] | 104 | = dyn_cast_or_null<ClassTemplateDecl>( | 
|  | 105 | SpecType->getTemplateName().getAsTemplateDecl())) { | 
| Douglas Gregor | 1530138 | 2009-07-30 17:40:51 +0000 | [diff] [blame] | 106 | QualType ContextType | 
|  | 107 | = Context.getCanonicalType(QualType(SpecType, 0)); | 
|  | 108 |  | 
| Douglas Gregor | d8d297c | 2009-07-21 23:53:31 +0000 | [diff] [blame] | 109 | // If the type of the nested name specifier is the same as the | 
|  | 110 | // injected class name of the named class template, we're entering | 
|  | 111 | // into that class template definition. | 
| John McCall | e78aac4 | 2010-03-10 03:28:59 +0000 | [diff] [blame] | 112 | QualType Injected | 
| Douglas Gregor | 9961ce9 | 2010-07-08 18:37:38 +0000 | [diff] [blame] | 113 | = ClassTemplate->getInjectedClassNameSpecialization(); | 
| Douglas Gregor | 1530138 | 2009-07-30 17:40:51 +0000 | [diff] [blame] | 114 | if (Context.hasSameType(Injected, ContextType)) | 
| Douglas Gregor | d8d297c | 2009-07-21 23:53:31 +0000 | [diff] [blame] | 115 | return ClassTemplate->getTemplatedDecl(); | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 116 |  | 
| Douglas Gregor | 1530138 | 2009-07-30 17:40:51 +0000 | [diff] [blame] | 117 | // If the type of the nested name specifier is the same as the | 
|  | 118 | // type of one of the class template's class template partial | 
|  | 119 | // specializations, we're entering into the definition of that | 
|  | 120 | // class template partial specialization. | 
|  | 121 | if (ClassTemplatePartialSpecializationDecl *PartialSpec | 
|  | 122 | = ClassTemplate->findPartialSpecialization(ContextType)) | 
|  | 123 | return PartialSpec; | 
| Douglas Gregor | d8d297c | 2009-07-21 23:53:31 +0000 | [diff] [blame] | 124 | } | 
| John McCall | e78aac4 | 2010-03-10 03:28:59 +0000 | [diff] [blame] | 125 | } else if (const RecordType *RecordT = NNSType->getAs<RecordType>()) { | 
| Douglas Gregor | e861bac | 2009-08-25 22:51:20 +0000 | [diff] [blame] | 126 | // The nested name specifier refers to a member of a class template. | 
|  | 127 | return RecordT->getDecl(); | 
| Douglas Gregor | d8d297c | 2009-07-21 23:53:31 +0000 | [diff] [blame] | 128 | } | 
|  | 129 | } | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 130 |  | 
| Douglas Gregor | d8d297c | 2009-07-21 23:53:31 +0000 | [diff] [blame] | 131 | return 0; | 
| Douglas Gregor | c9f9b86 | 2009-05-11 19:58:34 +0000 | [diff] [blame] | 132 | } | 
| Douglas Gregor | f21eb49 | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 133 |  | 
|  | 134 | switch (NNS->getKind()) { | 
|  | 135 | case NestedNameSpecifier::Identifier: | 
|  | 136 | assert(false && "Dependent nested-name-specifier has no DeclContext"); | 
|  | 137 | break; | 
|  | 138 |  | 
|  | 139 | case NestedNameSpecifier::Namespace: | 
|  | 140 | return NNS->getAsNamespace(); | 
|  | 141 |  | 
| Douglas Gregor | 7b26ff9 | 2011-02-24 02:36:08 +0000 | [diff] [blame] | 142 | case NestedNameSpecifier::NamespaceAlias: | 
|  | 143 | return NNS->getAsNamespaceAlias()->getNamespace(); | 
|  | 144 |  | 
| Douglas Gregor | f21eb49 | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 145 | case NestedNameSpecifier::TypeSpec: | 
|  | 146 | case NestedNameSpecifier::TypeSpecWithTemplate: { | 
| Douglas Gregor | cd3f49f | 2010-02-25 04:46:04 +0000 | [diff] [blame] | 147 | const TagType *Tag = NNS->getAsType()->getAs<TagType>(); | 
|  | 148 | assert(Tag && "Non-tag type in nested-name-specifier"); | 
|  | 149 | return Tag->getDecl(); | 
|  | 150 | } break; | 
| Douglas Gregor | f21eb49 | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 151 |  | 
|  | 152 | case NestedNameSpecifier::Global: | 
|  | 153 | return Context.getTranslationUnitDecl(); | 
|  | 154 | } | 
|  | 155 |  | 
| Douglas Gregor | cd3f49f | 2010-02-25 04:46:04 +0000 | [diff] [blame] | 156 | // Required to silence a GCC warning. | 
| Douglas Gregor | f21eb49 | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 157 | return 0; | 
| Douglas Gregor | 6bfde49 | 2009-03-18 00:36:05 +0000 | [diff] [blame] | 158 | } | 
|  | 159 |  | 
| Douglas Gregor | 90a1a65 | 2009-03-19 17:26:29 +0000 | [diff] [blame] | 160 | bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) { | 
|  | 161 | if (!SS.isSet() || SS.isInvalid()) | 
|  | 162 | return false; | 
|  | 163 |  | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 164 | NestedNameSpecifier *NNS | 
| Douglas Gregor | c23500e | 2009-03-26 23:56:24 +0000 | [diff] [blame] | 165 | = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); | 
| Douglas Gregor | f21eb49 | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 166 | return NNS->isDependent(); | 
| Douglas Gregor | 90a1a65 | 2009-03-19 17:26:29 +0000 | [diff] [blame] | 167 | } | 
|  | 168 |  | 
| Douglas Gregor | c9f9b86 | 2009-05-11 19:58:34 +0000 | [diff] [blame] | 169 | // \brief Determine whether this C++ scope specifier refers to an | 
|  | 170 | // unknown specialization, i.e., a dependent type that is not the | 
|  | 171 | // current instantiation. | 
|  | 172 | bool Sema::isUnknownSpecialization(const CXXScopeSpec &SS) { | 
|  | 173 | if (!isDependentScopeSpecifier(SS)) | 
|  | 174 | return false; | 
|  | 175 |  | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 176 | NestedNameSpecifier *NNS | 
| Douglas Gregor | c9f9b86 | 2009-05-11 19:58:34 +0000 | [diff] [blame] | 177 | = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); | 
|  | 178 | return getCurrentInstantiationOf(NNS) == 0; | 
|  | 179 | } | 
|  | 180 |  | 
|  | 181 | /// \brief If the given nested name specifier refers to the current | 
|  | 182 | /// instantiation, return the declaration that corresponds to that | 
|  | 183 | /// current instantiation (C++0x [temp.dep.type]p1). | 
|  | 184 | /// | 
|  | 185 | /// \param NNS a dependent nested name specifier. | 
|  | 186 | CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) { | 
|  | 187 | assert(getLangOptions().CPlusPlus && "Only callable in C++"); | 
|  | 188 | assert(NNS->isDependent() && "Only dependent nested-name-specifier allowed"); | 
|  | 189 |  | 
| Douglas Gregor | d8d297c | 2009-07-21 23:53:31 +0000 | [diff] [blame] | 190 | if (!NNS->getAsType()) | 
|  | 191 | return 0; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 192 |  | 
| Douglas Gregor | b9a955d | 2009-07-31 18:32:42 +0000 | [diff] [blame] | 193 | QualType T = QualType(NNS->getAsType(), 0); | 
| Douglas Gregor | bf2b26d | 2011-02-19 19:24:40 +0000 | [diff] [blame] | 194 | return ::getCurrentInstantiationOf(T, CurContext); | 
| Douglas Gregor | c9f9b86 | 2009-05-11 19:58:34 +0000 | [diff] [blame] | 195 | } | 
|  | 196 |  | 
| Douglas Gregor | 2689746 | 2009-03-11 16:48:53 +0000 | [diff] [blame] | 197 | /// \brief Require that the context specified by SS be complete. | 
|  | 198 | /// | 
|  | 199 | /// If SS refers to a type, this routine checks whether the type is | 
|  | 200 | /// complete enough (or can be made complete enough) for name lookup | 
|  | 201 | /// into the DeclContext. A type that is not yet completed can be | 
|  | 202 | /// considered "complete enough" if it is a class/struct/union/enum | 
|  | 203 | /// that is currently being defined. Or, if we have a type that names | 
|  | 204 | /// a class template specialization that is not a complete type, we | 
|  | 205 | /// will attempt to instantiate that class template. | 
| John McCall | 0b66eb3 | 2010-05-01 00:40:08 +0000 | [diff] [blame] | 206 | bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, | 
|  | 207 | DeclContext *DC) { | 
|  | 208 | assert(DC != 0 && "given null context"); | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 209 |  | 
| Douglas Gregor | 2689746 | 2009-03-11 16:48:53 +0000 | [diff] [blame] | 210 | if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) { | 
| Douglas Gregor | 8a6d15d | 2010-02-05 04:39:02 +0000 | [diff] [blame] | 211 | // If this is a dependent type, then we consider it complete. | 
|  | 212 | if (Tag->isDependentContext()) | 
|  | 213 | return false; | 
|  | 214 |  | 
| Douglas Gregor | 2689746 | 2009-03-11 16:48:53 +0000 | [diff] [blame] | 215 | // If we're currently defining this type, then lookup into the | 
|  | 216 | // type is okay: don't complain that it isn't complete yet. | 
| Ted Kremenek | c23c7e6 | 2009-07-29 21:53:49 +0000 | [diff] [blame] | 217 | const TagType *TagT = Context.getTypeDeclType(Tag)->getAs<TagType>(); | 
| John McCall | e78aac4 | 2010-03-10 03:28:59 +0000 | [diff] [blame] | 218 | if (TagT && TagT->isBeingDefined()) | 
| Douglas Gregor | 2689746 | 2009-03-11 16:48:53 +0000 | [diff] [blame] | 219 | return false; | 
|  | 220 |  | 
|  | 221 | // The type must be complete. | 
| Jeffrey Yasskin | c76498d | 2010-04-08 16:38:48 +0000 | [diff] [blame] | 222 | if (RequireCompleteType(SS.getRange().getBegin(), | 
|  | 223 | Context.getTypeDeclType(Tag), | 
|  | 224 | PDiag(diag::err_incomplete_nested_name_spec) | 
| John McCall | 0b66eb3 | 2010-05-01 00:40:08 +0000 | [diff] [blame] | 225 | << SS.getRange())) { | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 226 | SS.SetInvalid(SS.getRange()); | 
| Jeffrey Yasskin | c76498d | 2010-04-08 16:38:48 +0000 | [diff] [blame] | 227 | return true; | 
|  | 228 | } | 
| Douglas Gregor | 2689746 | 2009-03-11 16:48:53 +0000 | [diff] [blame] | 229 | } | 
|  | 230 |  | 
|  | 231 | return false; | 
|  | 232 | } | 
| Cedric Venet | 08438133 | 2009-02-14 20:20:19 +0000 | [diff] [blame] | 233 |  | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 234 | bool Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc, | 
|  | 235 | CXXScopeSpec &SS) { | 
|  | 236 | SS.MakeGlobal(Context, CCLoc); | 
|  | 237 | return false; | 
| Cedric Venet | 08438133 | 2009-02-14 20:20:19 +0000 | [diff] [blame] | 238 | } | 
|  | 239 |  | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 240 | /// \brief Determines whether the given declaration is an valid acceptable | 
|  | 241 | /// result for name lookup of a nested-name-specifier. | 
| Douglas Gregor | cd3f49f | 2010-02-25 04:46:04 +0000 | [diff] [blame] | 242 | bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD) { | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 243 | if (!SD) | 
|  | 244 | return false; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 245 |  | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 246 | // Namespace and namespace aliases are fine. | 
|  | 247 | if (isa<NamespaceDecl>(SD) || isa<NamespaceAliasDecl>(SD)) | 
|  | 248 | return true; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 249 |  | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 250 | if (!isa<TypeDecl>(SD)) | 
|  | 251 | return false; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 252 |  | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 253 | // Determine whether we have a class (or, in C++0x, an enum) or | 
|  | 254 | // a typedef thereof. If so, build the nested-name-specifier. | 
|  | 255 | QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD)); | 
|  | 256 | if (T->isDependentType()) | 
|  | 257 | return true; | 
| Richard Smith | dda56e4 | 2011-04-15 14:24:37 +0000 | [diff] [blame] | 258 | else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) { | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 259 | if (TD->getUnderlyingType()->isRecordType() || | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 260 | (Context.getLangOptions().CPlusPlus0x && | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 261 | TD->getUnderlyingType()->isEnumeralType())) | 
|  | 262 | return true; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 263 | } else if (isa<RecordDecl>(SD) || | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 264 | (Context.getLangOptions().CPlusPlus0x && isa<EnumDecl>(SD))) | 
|  | 265 | return true; | 
|  | 266 |  | 
|  | 267 | return false; | 
|  | 268 | } | 
|  | 269 |  | 
| Douglas Gregor | 2b6ca46 | 2009-09-03 21:38:09 +0000 | [diff] [blame] | 270 | /// \brief If the given nested-name-specifier begins with a bare identifier | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 271 | /// (e.g., Base::), perform name lookup for that identifier as a | 
| Douglas Gregor | 2b6ca46 | 2009-09-03 21:38:09 +0000 | [diff] [blame] | 272 | /// nested-name-specifier within the given scope, and return the result of that | 
|  | 273 | /// name lookup. | 
|  | 274 | NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) { | 
|  | 275 | if (!S || !NNS) | 
|  | 276 | return 0; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 277 |  | 
| Douglas Gregor | 2b6ca46 | 2009-09-03 21:38:09 +0000 | [diff] [blame] | 278 | while (NNS->getPrefix()) | 
|  | 279 | NNS = NNS->getPrefix(); | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 280 |  | 
| Douglas Gregor | 2b6ca46 | 2009-09-03 21:38:09 +0000 | [diff] [blame] | 281 | if (NNS->getKind() != NestedNameSpecifier::Identifier) | 
|  | 282 | return 0; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 283 |  | 
| John McCall | 27b18f8 | 2009-11-17 02:14:36 +0000 | [diff] [blame] | 284 | LookupResult Found(*this, NNS->getAsIdentifier(), SourceLocation(), | 
|  | 285 | LookupNestedNameSpecifierName); | 
|  | 286 | LookupName(Found, S); | 
| Douglas Gregor | 2b6ca46 | 2009-09-03 21:38:09 +0000 | [diff] [blame] | 287 | assert(!Found.isAmbiguous() && "Cannot handle ambiguities here yet"); | 
|  | 288 |  | 
| John McCall | 67c0087 | 2009-12-02 08:25:40 +0000 | [diff] [blame] | 289 | if (!Found.isSingleResult()) | 
|  | 290 | return 0; | 
|  | 291 |  | 
|  | 292 | NamedDecl *Result = Found.getFoundDecl(); | 
| Douglas Gregor | cd3f49f | 2010-02-25 04:46:04 +0000 | [diff] [blame] | 293 | if (isAcceptableNestedNameSpecifier(Result)) | 
| Douglas Gregor | 2b6ca46 | 2009-09-03 21:38:09 +0000 | [diff] [blame] | 294 | return Result; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 295 |  | 
| Douglas Gregor | 2b6ca46 | 2009-09-03 21:38:09 +0000 | [diff] [blame] | 296 | return 0; | 
|  | 297 | } | 
|  | 298 |  | 
| Jeffrey Yasskin | c76498d | 2010-04-08 16:38:48 +0000 | [diff] [blame] | 299 | bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS, | 
| Douglas Gregor | 0d5b0a1 | 2010-02-24 21:29:12 +0000 | [diff] [blame] | 300 | SourceLocation IdLoc, | 
|  | 301 | IdentifierInfo &II, | 
| John McCall | ba7bf59 | 2010-08-24 05:47:05 +0000 | [diff] [blame] | 302 | ParsedType ObjectTypePtr) { | 
| Douglas Gregor | 0d5b0a1 | 2010-02-24 21:29:12 +0000 | [diff] [blame] | 303 | QualType ObjectType = GetTypeFromParser(ObjectTypePtr); | 
|  | 304 | LookupResult Found(*this, &II, IdLoc, LookupNestedNameSpecifierName); | 
|  | 305 |  | 
|  | 306 | // Determine where to perform name lookup | 
|  | 307 | DeclContext *LookupCtx = 0; | 
|  | 308 | bool isDependent = false; | 
|  | 309 | if (!ObjectType.isNull()) { | 
|  | 310 | // This nested-name-specifier occurs in a member access expression, e.g., | 
|  | 311 | // x->B::f, and we are looking into the type of the object. | 
|  | 312 | assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist"); | 
|  | 313 | LookupCtx = computeDeclContext(ObjectType); | 
|  | 314 | isDependent = ObjectType->isDependentType(); | 
|  | 315 | } else if (SS.isSet()) { | 
|  | 316 | // This nested-name-specifier occurs after another nested-name-specifier, | 
|  | 317 | // so long into the context associated with the prior nested-name-specifier. | 
|  | 318 | LookupCtx = computeDeclContext(SS, false); | 
|  | 319 | isDependent = isDependentScopeSpecifier(SS); | 
|  | 320 | Found.setContextRange(SS.getRange()); | 
|  | 321 | } | 
|  | 322 |  | 
|  | 323 | if (LookupCtx) { | 
|  | 324 | // Perform "qualified" name lookup into the declaration context we | 
|  | 325 | // computed, which is either the type of the base of a member access | 
|  | 326 | // expression or the declaration context associated with a prior | 
|  | 327 | // nested-name-specifier. | 
|  | 328 |  | 
|  | 329 | // The declaration context must be complete. | 
| John McCall | 0b66eb3 | 2010-05-01 00:40:08 +0000 | [diff] [blame] | 330 | if (!LookupCtx->isDependentContext() && | 
|  | 331 | RequireCompleteDeclContext(SS, LookupCtx)) | 
| Douglas Gregor | 0d5b0a1 | 2010-02-24 21:29:12 +0000 | [diff] [blame] | 332 | return false; | 
|  | 333 |  | 
|  | 334 | LookupQualifiedName(Found, LookupCtx); | 
|  | 335 | } else if (isDependent) { | 
|  | 336 | return false; | 
|  | 337 | } else { | 
|  | 338 | LookupName(Found, S); | 
|  | 339 | } | 
|  | 340 | Found.suppressDiagnostics(); | 
|  | 341 |  | 
|  | 342 | if (NamedDecl *ND = Found.getAsSingle<NamedDecl>()) | 
|  | 343 | return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND); | 
|  | 344 |  | 
|  | 345 | return false; | 
|  | 346 | } | 
|  | 347 |  | 
| Douglas Gregor | 2b6ca46 | 2009-09-03 21:38:09 +0000 | [diff] [blame] | 348 | /// \brief Build a new nested-name-specifier for "identifier::", as described | 
|  | 349 | /// by ActOnCXXNestedNameSpecifier. | 
|  | 350 | /// | 
|  | 351 | /// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in | 
|  | 352 | /// that it contains an extra parameter \p ScopeLookupResult, which provides | 
|  | 353 | /// the result of name lookup within the scope of the nested-name-specifier | 
| Douglas Gregor | ad183ac | 2009-12-30 16:01:52 +0000 | [diff] [blame] | 354 | /// that was computed at template definition time. | 
| Chris Lattner | 1c42803 | 2009-12-07 01:36:53 +0000 | [diff] [blame] | 355 | /// | 
|  | 356 | /// If ErrorRecoveryLookup is true, then this call is used to improve error | 
|  | 357 | /// recovery.  This means that it should not emit diagnostics, it should | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 358 | /// just return true on failure.  It also means it should only return a valid | 
| Chris Lattner | 1c42803 | 2009-12-07 01:36:53 +0000 | [diff] [blame] | 359 | /// scope if it *knows* that the result is correct.  It should not return in a | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 360 | /// dependent context, for example. Nor will it extend \p SS with the scope | 
|  | 361 | /// specifier. | 
|  | 362 | bool Sema::BuildCXXNestedNameSpecifier(Scope *S, | 
|  | 363 | IdentifierInfo &Identifier, | 
|  | 364 | SourceLocation IdentifierLoc, | 
|  | 365 | SourceLocation CCLoc, | 
|  | 366 | QualType ObjectType, | 
|  | 367 | bool EnteringContext, | 
|  | 368 | CXXScopeSpec &SS, | 
|  | 369 | NamedDecl *ScopeLookupResult, | 
|  | 370 | bool ErrorRecoveryLookup) { | 
|  | 371 | LookupResult Found(*this, &Identifier, IdentifierLoc, | 
|  | 372 | LookupNestedNameSpecifierName); | 
| John McCall | 27b18f8 | 2009-11-17 02:14:36 +0000 | [diff] [blame] | 373 |  | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 374 | // Determine where to perform name lookup | 
|  | 375 | DeclContext *LookupCtx = 0; | 
|  | 376 | bool isDependent = false; | 
| Douglas Gregor | 2b6ca46 | 2009-09-03 21:38:09 +0000 | [diff] [blame] | 377 | if (!ObjectType.isNull()) { | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 378 | // This nested-name-specifier occurs in a member access expression, e.g., | 
|  | 379 | // x->B::f, and we are looking into the type of the object. | 
|  | 380 | assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist"); | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 381 | LookupCtx = computeDeclContext(ObjectType); | 
|  | 382 | isDependent = ObjectType->isDependentType(); | 
|  | 383 | } else if (SS.isSet()) { | 
|  | 384 | // This nested-name-specifier occurs after another nested-name-specifier, | 
|  | 385 | // so long into the context associated with the prior nested-name-specifier. | 
|  | 386 | LookupCtx = computeDeclContext(SS, EnteringContext); | 
|  | 387 | isDependent = isDependentScopeSpecifier(SS); | 
| John McCall | 27b18f8 | 2009-11-17 02:14:36 +0000 | [diff] [blame] | 388 | Found.setContextRange(SS.getRange()); | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 389 | } | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 390 |  | 
| John McCall | 27b18f8 | 2009-11-17 02:14:36 +0000 | [diff] [blame] | 391 |  | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 392 | bool ObjectTypeSearchedInScope = false; | 
|  | 393 | if (LookupCtx) { | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 394 | // Perform "qualified" name lookup into the declaration context we | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 395 | // computed, which is either the type of the base of a member access | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 396 | // expression or the declaration context associated with a prior | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 397 | // nested-name-specifier. | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 398 |  | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 399 | // The declaration context must be complete. | 
| John McCall | 0b66eb3 | 2010-05-01 00:40:08 +0000 | [diff] [blame] | 400 | if (!LookupCtx->isDependentContext() && | 
|  | 401 | RequireCompleteDeclContext(SS, LookupCtx)) | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 402 | return true; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 403 |  | 
| John McCall | 27b18f8 | 2009-11-17 02:14:36 +0000 | [diff] [blame] | 404 | LookupQualifiedName(Found, LookupCtx); | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 405 |  | 
| John McCall | 27b18f8 | 2009-11-17 02:14:36 +0000 | [diff] [blame] | 406 | if (!ObjectType.isNull() && Found.empty()) { | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 407 | // C++ [basic.lookup.classref]p4: | 
|  | 408 | //   If the id-expression in a class member access is a qualified-id of | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 409 | //   the form | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 410 | // | 
|  | 411 | //        class-name-or-namespace-name::... | 
|  | 412 | // | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 413 | //   the class-name-or-namespace-name following the . or -> operator is | 
|  | 414 | //   looked up both in the context of the entire postfix-expression and in | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 415 | //   the scope of the class of the object expression. If the name is found | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 416 | //   only in the scope of the class of the object expression, the name | 
|  | 417 | //   shall refer to a class-name. If the name is found only in the | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 418 | //   context of the entire postfix-expression, the name shall refer to a | 
|  | 419 | //   class-name or namespace-name. [...] | 
|  | 420 | // | 
|  | 421 | // Qualified name lookup into a class will not find a namespace-name, | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 422 | // so we do not need to diagnoste that case specifically. However, | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 423 | // this qualified name lookup may find nothing. In that case, perform | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 424 | // unqualified name lookup in the given scope (if available) or | 
| Douglas Gregor | 2b6ca46 | 2009-09-03 21:38:09 +0000 | [diff] [blame] | 425 | // reconstruct the result from when name lookup was performed at template | 
|  | 426 | // definition time. | 
|  | 427 | if (S) | 
| John McCall | 27b18f8 | 2009-11-17 02:14:36 +0000 | [diff] [blame] | 428 | LookupName(Found, S); | 
| John McCall | 9f3059a | 2009-10-09 21:13:30 +0000 | [diff] [blame] | 429 | else if (ScopeLookupResult) | 
|  | 430 | Found.addDecl(ScopeLookupResult); | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 431 |  | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 432 | ObjectTypeSearchedInScope = true; | 
|  | 433 | } | 
| Douglas Gregor | df65c8ed | 2010-07-28 14:49:07 +0000 | [diff] [blame] | 434 | } else if (!isDependent) { | 
|  | 435 | // Perform unqualified name lookup in the current scope. | 
|  | 436 | LookupName(Found, S); | 
|  | 437 | } | 
|  | 438 |  | 
|  | 439 | // If we performed lookup into a dependent context and did not find anything, | 
|  | 440 | // that's fine: just build a dependent nested-name-specifier. | 
|  | 441 | if (Found.empty() && isDependent && | 
|  | 442 | !(LookupCtx && LookupCtx->isRecord() && | 
|  | 443 | (!cast<CXXRecordDecl>(LookupCtx)->hasDefinition() || | 
|  | 444 | !cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()))) { | 
| Chris Lattner | 1c42803 | 2009-12-07 01:36:53 +0000 | [diff] [blame] | 445 | // Don't speculate if we're just trying to improve error recovery. | 
|  | 446 | if (ErrorRecoveryLookup) | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 447 | return true; | 
| Chris Lattner | 1c42803 | 2009-12-07 01:36:53 +0000 | [diff] [blame] | 448 |  | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 449 | // We were not able to compute the declaration context for a dependent | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 450 | // base object type or prior nested-name-specifier, so this | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 451 | // nested-name-specifier refers to an unknown specialization. Just build | 
|  | 452 | // a dependent nested-name-specifier. | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 453 | SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc); | 
|  | 454 | return false; | 
| Douglas Gregor | df65c8ed | 2010-07-28 14:49:07 +0000 | [diff] [blame] | 455 | } | 
|  | 456 |  | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 457 | // FIXME: Deal with ambiguities cleanly. | 
| Douglas Gregor | 532e68f | 2009-12-31 08:26:35 +0000 | [diff] [blame] | 458 |  | 
|  | 459 | if (Found.empty() && !ErrorRecoveryLookup) { | 
|  | 460 | // We haven't found anything, and we're not recovering from a | 
|  | 461 | // different kind of error, so look for typos. | 
|  | 462 | DeclarationName Name = Found.getLookupName(); | 
| Douglas Gregor | 280e1ee | 2010-04-14 20:04:41 +0000 | [diff] [blame] | 463 | if (CorrectTypo(Found, S, &SS, LookupCtx, EnteringContext, | 
|  | 464 | CTC_NoKeywords) && | 
| Douglas Gregor | 532e68f | 2009-12-31 08:26:35 +0000 | [diff] [blame] | 465 | Found.isSingleResult() && | 
| Douglas Gregor | cd3f49f | 2010-02-25 04:46:04 +0000 | [diff] [blame] | 466 | isAcceptableNestedNameSpecifier(Found.getAsSingle<NamedDecl>())) { | 
| Douglas Gregor | 532e68f | 2009-12-31 08:26:35 +0000 | [diff] [blame] | 467 | if (LookupCtx) | 
|  | 468 | Diag(Found.getNameLoc(), diag::err_no_member_suggest) | 
|  | 469 | << Name << LookupCtx << Found.getLookupName() << SS.getRange() | 
| Douglas Gregor | a771f46 | 2010-03-31 17:46:05 +0000 | [diff] [blame] | 470 | << FixItHint::CreateReplacement(Found.getNameLoc(), | 
|  | 471 | Found.getLookupName().getAsString()); | 
| Douglas Gregor | 532e68f | 2009-12-31 08:26:35 +0000 | [diff] [blame] | 472 | else | 
|  | 473 | Diag(Found.getNameLoc(), diag::err_undeclared_var_use_suggest) | 
|  | 474 | << Name << Found.getLookupName() | 
| Douglas Gregor | a771f46 | 2010-03-31 17:46:05 +0000 | [diff] [blame] | 475 | << FixItHint::CreateReplacement(Found.getNameLoc(), | 
|  | 476 | Found.getLookupName().getAsString()); | 
| Douglas Gregor | 6da8362 | 2010-01-07 00:17:44 +0000 | [diff] [blame] | 477 |  | 
|  | 478 | if (NamedDecl *ND = Found.getAsSingle<NamedDecl>()) | 
|  | 479 | Diag(ND->getLocation(), diag::note_previous_decl) | 
|  | 480 | << ND->getDeclName(); | 
| Douglas Gregor | c048c52 | 2010-06-29 19:27:42 +0000 | [diff] [blame] | 481 | } else { | 
| Douglas Gregor | 532e68f | 2009-12-31 08:26:35 +0000 | [diff] [blame] | 482 | Found.clear(); | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 483 | Found.setLookupName(&Identifier); | 
| Douglas Gregor | c048c52 | 2010-06-29 19:27:42 +0000 | [diff] [blame] | 484 | } | 
| Douglas Gregor | 532e68f | 2009-12-31 08:26:35 +0000 | [diff] [blame] | 485 | } | 
|  | 486 |  | 
| John McCall | 67c0087 | 2009-12-02 08:25:40 +0000 | [diff] [blame] | 487 | NamedDecl *SD = Found.getAsSingle<NamedDecl>(); | 
| Douglas Gregor | cd3f49f | 2010-02-25 04:46:04 +0000 | [diff] [blame] | 488 | if (isAcceptableNestedNameSpecifier(SD)) { | 
| Douglas Gregor | 2b6ca46 | 2009-09-03 21:38:09 +0000 | [diff] [blame] | 489 | if (!ObjectType.isNull() && !ObjectTypeSearchedInScope) { | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 490 | // C++ [basic.lookup.classref]p4: | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 491 | //   [...] If the name is found in both contexts, the | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 492 | //   class-name-or-namespace-name shall refer to the same entity. | 
|  | 493 | // | 
|  | 494 | // We already found the name in the scope of the object. Now, look | 
|  | 495 | // into the current scope (the scope of the postfix-expression) to | 
| Douglas Gregor | 2b6ca46 | 2009-09-03 21:38:09 +0000 | [diff] [blame] | 496 | // see if we can find the same name there. As above, if there is no | 
|  | 497 | // scope, reconstruct the result from the template instantiation itself. | 
| John McCall | 9f3059a | 2009-10-09 21:13:30 +0000 | [diff] [blame] | 498 | NamedDecl *OuterDecl; | 
|  | 499 | if (S) { | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 500 | LookupResult FoundOuter(*this, &Identifier, IdentifierLoc, | 
|  | 501 | LookupNestedNameSpecifierName); | 
| John McCall | 27b18f8 | 2009-11-17 02:14:36 +0000 | [diff] [blame] | 502 | LookupName(FoundOuter, S); | 
| John McCall | 67c0087 | 2009-12-02 08:25:40 +0000 | [diff] [blame] | 503 | OuterDecl = FoundOuter.getAsSingle<NamedDecl>(); | 
| John McCall | 9f3059a | 2009-10-09 21:13:30 +0000 | [diff] [blame] | 504 | } else | 
|  | 505 | OuterDecl = ScopeLookupResult; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 506 |  | 
| Douglas Gregor | cd3f49f | 2010-02-25 04:46:04 +0000 | [diff] [blame] | 507 | if (isAcceptableNestedNameSpecifier(OuterDecl) && | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 508 | OuterDecl->getCanonicalDecl() != SD->getCanonicalDecl() && | 
|  | 509 | (!isa<TypeDecl>(OuterDecl) || !isa<TypeDecl>(SD) || | 
|  | 510 | !Context.hasSameType( | 
| Douglas Gregor | 2b6ca46 | 2009-09-03 21:38:09 +0000 | [diff] [blame] | 511 | Context.getTypeDeclType(cast<TypeDecl>(OuterDecl)), | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 512 | Context.getTypeDeclType(cast<TypeDecl>(SD))))) { | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 513 | if (ErrorRecoveryLookup) | 
|  | 514 | return true; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 515 |  | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 516 | Diag(IdentifierLoc, | 
|  | 517 | diag::err_nested_name_member_ref_lookup_ambiguous) | 
|  | 518 | << &Identifier; | 
|  | 519 | Diag(SD->getLocation(), diag::note_ambig_member_ref_object_type) | 
|  | 520 | << ObjectType; | 
|  | 521 | Diag(OuterDecl->getLocation(), diag::note_ambig_member_ref_scope); | 
|  | 522 |  | 
|  | 523 | // Fall through so that we'll pick the name we found in the object | 
|  | 524 | // type, since that's probably what the user wanted anyway. | 
|  | 525 | } | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 526 | } | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 527 |  | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 528 | // If we're just performing this lookup for error-recovery purposes, | 
|  | 529 | // don't extend the nested-name-specifier. Just return now. | 
|  | 530 | if (ErrorRecoveryLookup) | 
|  | 531 | return false; | 
|  | 532 |  | 
|  | 533 | if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD)) { | 
|  | 534 | SS.Extend(Context, Namespace, IdentifierLoc, CCLoc); | 
|  | 535 | return false; | 
|  | 536 | } | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 537 |  | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 538 | if (NamespaceAliasDecl *Alias = dyn_cast<NamespaceAliasDecl>(SD)) { | 
| Douglas Gregor | 7b26ff9 | 2011-02-24 02:36:08 +0000 | [diff] [blame] | 539 | SS.Extend(Context, Alias, IdentifierLoc, CCLoc); | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 540 | return false; | 
|  | 541 | } | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 542 |  | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 543 | QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD)); | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 544 | TypeLocBuilder TLB; | 
|  | 545 | if (isa<InjectedClassNameType>(T)) { | 
|  | 546 | InjectedClassNameTypeLoc InjectedTL | 
|  | 547 | = TLB.push<InjectedClassNameTypeLoc>(T); | 
|  | 548 | InjectedTL.setNameLoc(IdentifierLoc); | 
| Douglas Gregor | dfd4b74 | 2011-05-04 23:05:40 +0000 | [diff] [blame] | 549 | } else if (isa<RecordType>(T)) { | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 550 | RecordTypeLoc RecordTL = TLB.push<RecordTypeLoc>(T); | 
|  | 551 | RecordTL.setNameLoc(IdentifierLoc); | 
| Douglas Gregor | dfd4b74 | 2011-05-04 23:05:40 +0000 | [diff] [blame] | 552 | } else if (isa<TypedefType>(T)) { | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 553 | TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(T); | 
|  | 554 | TypedefTL.setNameLoc(IdentifierLoc); | 
| Douglas Gregor | dfd4b74 | 2011-05-04 23:05:40 +0000 | [diff] [blame] | 555 | } else if (isa<EnumType>(T)) { | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 556 | EnumTypeLoc EnumTL = TLB.push<EnumTypeLoc>(T); | 
|  | 557 | EnumTL.setNameLoc(IdentifierLoc); | 
| Douglas Gregor | dfd4b74 | 2011-05-04 23:05:40 +0000 | [diff] [blame] | 558 | } else if (isa<TemplateTypeParmType>(T)) { | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 559 | TemplateTypeParmTypeLoc TemplateTypeTL | 
|  | 560 | = TLB.push<TemplateTypeParmTypeLoc>(T); | 
|  | 561 | TemplateTypeTL.setNameLoc(IdentifierLoc); | 
| Douglas Gregor | dfd4b74 | 2011-05-04 23:05:40 +0000 | [diff] [blame] | 562 | } else if (isa<UnresolvedUsingType>(T)) { | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 563 | UnresolvedUsingTypeLoc UnresolvedTL | 
|  | 564 | = TLB.push<UnresolvedUsingTypeLoc>(T); | 
|  | 565 | UnresolvedTL.setNameLoc(IdentifierLoc); | 
| Douglas Gregor | dfd4b74 | 2011-05-04 23:05:40 +0000 | [diff] [blame] | 566 | } else if (isa<SubstTemplateTypeParmType>(T)) { | 
|  | 567 | SubstTemplateTypeParmTypeLoc TL | 
|  | 568 | = TLB.push<SubstTemplateTypeParmTypeLoc>(T); | 
|  | 569 | TL.setNameLoc(IdentifierLoc); | 
|  | 570 | } else if (isa<SubstTemplateTypeParmPackType>(T)) { | 
|  | 571 | SubstTemplateTypeParmPackTypeLoc TL | 
|  | 572 | = TLB.push<SubstTemplateTypeParmPackTypeLoc>(T); | 
|  | 573 | TL.setNameLoc(IdentifierLoc); | 
|  | 574 | } else { | 
|  | 575 | llvm_unreachable("Unhandled TypeDecl node in nested-name-specifier"); | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 576 | } | 
|  | 577 |  | 
|  | 578 | SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T), | 
|  | 579 | CCLoc); | 
|  | 580 | return false; | 
| Douglas Gregor | b7bfe79 | 2009-09-02 22:59:36 +0000 | [diff] [blame] | 581 | } | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 582 |  | 
| Chris Lattner | 1c42803 | 2009-12-07 01:36:53 +0000 | [diff] [blame] | 583 | // Otherwise, we have an error case.  If we don't want diagnostics, just | 
|  | 584 | // return an error now. | 
|  | 585 | if (ErrorRecoveryLookup) | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 586 | return true; | 
| Chris Lattner | 1c42803 | 2009-12-07 01:36:53 +0000 | [diff] [blame] | 587 |  | 
| Cedric Venet | 08438133 | 2009-02-14 20:20:19 +0000 | [diff] [blame] | 588 | // If we didn't find anything during our lookup, try again with | 
|  | 589 | // ordinary name lookup, which can help us produce better error | 
|  | 590 | // messages. | 
| John McCall | 67c0087 | 2009-12-02 08:25:40 +0000 | [diff] [blame] | 591 | if (Found.empty()) { | 
| John McCall | 27b18f8 | 2009-11-17 02:14:36 +0000 | [diff] [blame] | 592 | Found.clear(LookupOrdinaryName); | 
|  | 593 | LookupName(Found, S); | 
| John McCall | 9f3059a | 2009-10-09 21:13:30 +0000 | [diff] [blame] | 594 | } | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 595 |  | 
| Cedric Venet | 08438133 | 2009-02-14 20:20:19 +0000 | [diff] [blame] | 596 | unsigned DiagID; | 
| John McCall | 67c0087 | 2009-12-02 08:25:40 +0000 | [diff] [blame] | 597 | if (!Found.empty()) | 
| Cedric Venet | 08438133 | 2009-02-14 20:20:19 +0000 | [diff] [blame] | 598 | DiagID = diag::err_expected_class_or_namespace; | 
| Anders Carlsson | b533df0 | 2009-08-30 07:09:50 +0000 | [diff] [blame] | 599 | else if (SS.isSet()) { | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 600 | Diag(IdentifierLoc, diag::err_no_member) | 
|  | 601 | << &Identifier << LookupCtx << SS.getRange(); | 
|  | 602 | return true; | 
| Anders Carlsson | b533df0 | 2009-08-30 07:09:50 +0000 | [diff] [blame] | 603 | } else | 
| Cedric Venet | 08438133 | 2009-02-14 20:20:19 +0000 | [diff] [blame] | 604 | DiagID = diag::err_undeclared_var_use; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 605 |  | 
| Cedric Venet | 08438133 | 2009-02-14 20:20:19 +0000 | [diff] [blame] | 606 | if (SS.isSet()) | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 607 | Diag(IdentifierLoc, DiagID) << &Identifier << SS.getRange(); | 
| Cedric Venet | 08438133 | 2009-02-14 20:20:19 +0000 | [diff] [blame] | 608 | else | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 609 | Diag(IdentifierLoc, DiagID) << &Identifier; | 
| Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 610 |  | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 611 | return true; | 
| Cedric Venet | 08438133 | 2009-02-14 20:20:19 +0000 | [diff] [blame] | 612 | } | 
|  | 613 |  | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 614 | bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, | 
|  | 615 | IdentifierInfo &Identifier, | 
|  | 616 | SourceLocation IdentifierLoc, | 
|  | 617 | SourceLocation CCLoc, | 
|  | 618 | ParsedType ObjectType, | 
|  | 619 | bool EnteringContext, | 
|  | 620 | CXXScopeSpec &SS) { | 
|  | 621 | if (SS.isInvalid()) | 
|  | 622 | return true; | 
|  | 623 |  | 
|  | 624 | return BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, CCLoc, | 
|  | 625 | GetTypeFromParser(ObjectType), | 
|  | 626 | EnteringContext, SS, | 
|  | 627 | /*ScopeLookupResult=*/0, false); | 
| Chris Lattner | 1c42803 | 2009-12-07 01:36:53 +0000 | [diff] [blame] | 628 | } | 
|  | 629 |  | 
|  | 630 | /// IsInvalidUnlessNestedName - This method is used for error recovery | 
|  | 631 | /// purposes to determine whether the specified identifier is only valid as | 
|  | 632 | /// a nested name specifier, for example a namespace name.  It is | 
|  | 633 | /// conservatively correct to always return false from this method. | 
|  | 634 | /// | 
|  | 635 | /// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier. | 
| Jeffrey Yasskin | c76498d | 2010-04-08 16:38:48 +0000 | [diff] [blame] | 636 | bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 637 | IdentifierInfo &Identifier, | 
|  | 638 | SourceLocation IdentifierLoc, | 
|  | 639 | SourceLocation ColonLoc, | 
|  | 640 | ParsedType ObjectType, | 
| Chris Lattner | 1c42803 | 2009-12-07 01:36:53 +0000 | [diff] [blame] | 641 | bool EnteringContext) { | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 642 | if (SS.isInvalid()) | 
|  | 643 | return false; | 
|  | 644 |  | 
|  | 645 | return !BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, ColonLoc, | 
|  | 646 | GetTypeFromParser(ObjectType), | 
|  | 647 | EnteringContext, SS, | 
|  | 648 | /*ScopeLookupResult=*/0, true); | 
| Douglas Gregor | 2b6ca46 | 2009-09-03 21:38:09 +0000 | [diff] [blame] | 649 | } | 
|  | 650 |  | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 651 | bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, | 
| Douglas Gregor | 6e06801 | 2011-02-28 00:04:36 +0000 | [diff] [blame] | 652 | SourceLocation TemplateLoc, | 
|  | 653 | CXXScopeSpec &SS, | 
|  | 654 | TemplateTy Template, | 
|  | 655 | SourceLocation TemplateNameLoc, | 
|  | 656 | SourceLocation LAngleLoc, | 
|  | 657 | ASTTemplateArgsPtr TemplateArgsIn, | 
|  | 658 | SourceLocation RAngleLoc, | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 659 | SourceLocation CCLoc, | 
| Douglas Gregor | 6e06801 | 2011-02-28 00:04:36 +0000 | [diff] [blame] | 660 | bool EnteringContext) { | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 661 | if (SS.isInvalid()) | 
|  | 662 | return true; | 
|  | 663 |  | 
| Douglas Gregor | 6e06801 | 2011-02-28 00:04:36 +0000 | [diff] [blame] | 664 | // Translate the parser's template argument list in our AST format. | 
|  | 665 | TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); | 
|  | 666 | translateTemplateArguments(TemplateArgsIn, TemplateArgs); | 
|  | 667 |  | 
|  | 668 | if (DependentTemplateName *DTN = Template.get().getAsDependentTemplateName()){ | 
|  | 669 | // Handle a dependent template specialization for which we cannot resolve | 
|  | 670 | // the template name. | 
|  | 671 | assert(DTN->getQualifier() | 
|  | 672 | == static_cast<NestedNameSpecifier*>(SS.getScopeRep())); | 
|  | 673 | QualType T = Context.getDependentTemplateSpecializationType(ETK_None, | 
| Douglas Gregor | a7a795b | 2011-03-01 20:11:18 +0000 | [diff] [blame] | 674 | DTN->getQualifier(), | 
|  | 675 | DTN->getIdentifier(), | 
| Douglas Gregor | 6e06801 | 2011-02-28 00:04:36 +0000 | [diff] [blame] | 676 | TemplateArgs); | 
|  | 677 |  | 
|  | 678 | // Create source-location information for this type. | 
|  | 679 | TypeLocBuilder Builder; | 
|  | 680 | DependentTemplateSpecializationTypeLoc SpecTL | 
|  | 681 | = Builder.push<DependentTemplateSpecializationTypeLoc>(T); | 
|  | 682 | SpecTL.setLAngleLoc(LAngleLoc); | 
|  | 683 | SpecTL.setRAngleLoc(RAngleLoc); | 
|  | 684 | SpecTL.setKeywordLoc(SourceLocation()); | 
|  | 685 | SpecTL.setNameLoc(TemplateNameLoc); | 
| Douglas Gregor | a7a795b | 2011-03-01 20:11:18 +0000 | [diff] [blame] | 686 | SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); | 
| Douglas Gregor | 6e06801 | 2011-02-28 00:04:36 +0000 | [diff] [blame] | 687 | for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) | 
|  | 688 | SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); | 
|  | 689 |  | 
|  | 690 | SS.Extend(Context, TemplateLoc, Builder.getTypeLocInContext(Context, T), | 
|  | 691 | CCLoc); | 
|  | 692 | return false; | 
|  | 693 | } | 
|  | 694 |  | 
| Douglas Gregor | 8b6070b | 2011-03-04 21:37:14 +0000 | [diff] [blame] | 695 |  | 
|  | 696 | if (Template.get().getAsOverloadedTemplate() || | 
|  | 697 | isa<FunctionTemplateDecl>(Template.get().getAsTemplateDecl())) { | 
|  | 698 | SourceRange R(TemplateNameLoc, RAngleLoc); | 
|  | 699 | if (SS.getRange().isValid()) | 
|  | 700 | R.setBegin(SS.getRange().getBegin()); | 
|  | 701 |  | 
|  | 702 | Diag(CCLoc, diag::err_non_type_template_in_nested_name_specifier) | 
|  | 703 | << Template.get() << R; | 
|  | 704 | NoteAllFoundTemplates(Template.get()); | 
|  | 705 | return true; | 
|  | 706 | } | 
|  | 707 |  | 
| Douglas Gregor | 6e06801 | 2011-02-28 00:04:36 +0000 | [diff] [blame] | 708 | // We were able to resolve the template name to an actual template. | 
|  | 709 | // Build an appropriate nested-name-specifier. | 
|  | 710 | QualType T = CheckTemplateIdType(Template.get(), TemplateNameLoc, | 
|  | 711 | TemplateArgs); | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 712 | if (T.isNull()) | 
|  | 713 | return true; | 
|  | 714 |  | 
| Douglas Gregor | 6e06801 | 2011-02-28 00:04:36 +0000 | [diff] [blame] | 715 | // FIXME: Template aliases will need to check the resulting type to make | 
|  | 716 | // sure that it's either dependent or a tag type. | 
|  | 717 |  | 
|  | 718 | // Provide source-location information for the template specialization | 
|  | 719 | // type. | 
|  | 720 | TypeLocBuilder Builder; | 
|  | 721 | TemplateSpecializationTypeLoc SpecTL | 
|  | 722 | = Builder.push<TemplateSpecializationTypeLoc>(T); | 
|  | 723 |  | 
|  | 724 | SpecTL.setLAngleLoc(LAngleLoc); | 
|  | 725 | SpecTL.setRAngleLoc(RAngleLoc); | 
|  | 726 | SpecTL.setTemplateNameLoc(TemplateNameLoc); | 
|  | 727 | for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) | 
|  | 728 | SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); | 
|  | 729 |  | 
|  | 730 |  | 
|  | 731 | SS.Extend(Context, TemplateLoc, Builder.getTypeLocInContext(Context, T), | 
|  | 732 | CCLoc); | 
| Douglas Gregor | 90c9972 | 2011-02-24 00:17:56 +0000 | [diff] [blame] | 733 | return false; | 
| Douglas Gregor | 7f74112 | 2009-02-25 19:37:18 +0000 | [diff] [blame] | 734 | } | 
|  | 735 |  | 
| Douglas Gregor | 869ad45 | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 736 | namespace { | 
|  | 737 | /// \brief A structure that stores a nested-name-specifier annotation, | 
|  | 738 | /// including both the nested-name-specifier | 
|  | 739 | struct NestedNameSpecifierAnnotation { | 
|  | 740 | NestedNameSpecifier *NNS; | 
|  | 741 | }; | 
|  | 742 | } | 
|  | 743 |  | 
|  | 744 | void *Sema::SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS) { | 
|  | 745 | if (SS.isEmpty() || SS.isInvalid()) | 
|  | 746 | return 0; | 
|  | 747 |  | 
|  | 748 | void *Mem = Context.Allocate((sizeof(NestedNameSpecifierAnnotation) + | 
|  | 749 | SS.location_size()), | 
|  | 750 | llvm::alignOf<NestedNameSpecifierAnnotation>()); | 
|  | 751 | NestedNameSpecifierAnnotation *Annotation | 
|  | 752 | = new (Mem) NestedNameSpecifierAnnotation; | 
|  | 753 | Annotation->NNS = SS.getScopeRep(); | 
|  | 754 | memcpy(Annotation + 1, SS.location_data(), SS.location_size()); | 
|  | 755 | return Annotation; | 
|  | 756 | } | 
|  | 757 |  | 
|  | 758 | void Sema::RestoreNestedNameSpecifierAnnotation(void *AnnotationPtr, | 
|  | 759 | SourceRange AnnotationRange, | 
|  | 760 | CXXScopeSpec &SS) { | 
|  | 761 | if (!AnnotationPtr) { | 
|  | 762 | SS.SetInvalid(AnnotationRange); | 
|  | 763 | return; | 
|  | 764 | } | 
|  | 765 |  | 
|  | 766 | NestedNameSpecifierAnnotation *Annotation | 
|  | 767 | = static_cast<NestedNameSpecifierAnnotation *>(AnnotationPtr); | 
|  | 768 | SS.Adopt(NestedNameSpecifierLoc(Annotation->NNS, Annotation + 1)); | 
|  | 769 | } | 
|  | 770 |  | 
| John McCall | 2b058ef | 2009-12-11 20:04:54 +0000 | [diff] [blame] | 771 | bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { | 
|  | 772 | assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); | 
|  | 773 |  | 
|  | 774 | NestedNameSpecifier *Qualifier = | 
|  | 775 | static_cast<NestedNameSpecifier*>(SS.getScopeRep()); | 
|  | 776 |  | 
|  | 777 | // There are only two places a well-formed program may qualify a | 
|  | 778 | // declarator: first, when defining a namespace or class member | 
|  | 779 | // out-of-line, and second, when naming an explicitly-qualified | 
|  | 780 | // friend function.  The latter case is governed by | 
|  | 781 | // C++03 [basic.lookup.unqual]p10: | 
|  | 782 | //   In a friend declaration naming a member function, a name used | 
|  | 783 | //   in the function declarator and not part of a template-argument | 
|  | 784 | //   in a template-id is first looked up in the scope of the member | 
|  | 785 | //   function's class. If it is not found, or if the name is part of | 
|  | 786 | //   a template-argument in a template-id, the look up is as | 
|  | 787 | //   described for unqualified names in the definition of the class | 
|  | 788 | //   granting friendship. | 
|  | 789 | // i.e. we don't push a scope unless it's a class member. | 
|  | 790 |  | 
|  | 791 | switch (Qualifier->getKind()) { | 
|  | 792 | case NestedNameSpecifier::Global: | 
|  | 793 | case NestedNameSpecifier::Namespace: | 
| Douglas Gregor | 7b26ff9 | 2011-02-24 02:36:08 +0000 | [diff] [blame] | 794 | case NestedNameSpecifier::NamespaceAlias: | 
| John McCall | 2b058ef | 2009-12-11 20:04:54 +0000 | [diff] [blame] | 795 | // These are always namespace scopes.  We never want to enter a | 
|  | 796 | // namespace scope from anything but a file context. | 
| Sebastian Redl | 50c6825 | 2010-08-31 00:36:30 +0000 | [diff] [blame] | 797 | return CurContext->getRedeclContext()->isFileContext(); | 
| John McCall | 2b058ef | 2009-12-11 20:04:54 +0000 | [diff] [blame] | 798 |  | 
|  | 799 | case NestedNameSpecifier::Identifier: | 
|  | 800 | case NestedNameSpecifier::TypeSpec: | 
|  | 801 | case NestedNameSpecifier::TypeSpecWithTemplate: | 
|  | 802 | // These are never namespace scopes. | 
|  | 803 | return true; | 
|  | 804 | } | 
|  | 805 |  | 
|  | 806 | // Silence bogus warning. | 
|  | 807 | return false; | 
|  | 808 | } | 
|  | 809 |  | 
| Cedric Venet | 08438133 | 2009-02-14 20:20:19 +0000 | [diff] [blame] | 810 | /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global | 
|  | 811 | /// scope or nested-name-specifier) is parsed, part of a declarator-id. | 
|  | 812 | /// After this method is called, according to [C++ 3.4.3p3], names should be | 
|  | 813 | /// looked up in the declarator-id's scope, until the declarator is parsed and | 
|  | 814 | /// ActOnCXXExitDeclaratorScope is called. | 
|  | 815 | /// The 'SS' should be a non-empty valid CXXScopeSpec. | 
| Jeffrey Yasskin | c76498d | 2010-04-08 16:38:48 +0000 | [diff] [blame] | 816 | bool Sema::ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS) { | 
| Cedric Venet | 08438133 | 2009-02-14 20:20:19 +0000 | [diff] [blame] | 817 | assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); | 
| John McCall | 6df5fef | 2009-12-19 10:49:29 +0000 | [diff] [blame] | 818 |  | 
|  | 819 | if (SS.isInvalid()) return true; | 
|  | 820 |  | 
|  | 821 | DeclContext *DC = computeDeclContext(SS, true); | 
|  | 822 | if (!DC) return true; | 
|  | 823 |  | 
|  | 824 | // Before we enter a declarator's context, we need to make sure that | 
|  | 825 | // it is a complete declaration context. | 
| John McCall | 0b66eb3 | 2010-05-01 00:40:08 +0000 | [diff] [blame] | 826 | if (!DC->isDependentContext() && RequireCompleteDeclContext(SS, DC)) | 
| John McCall | 6df5fef | 2009-12-19 10:49:29 +0000 | [diff] [blame] | 827 | return true; | 
|  | 828 |  | 
|  | 829 | EnterDeclaratorContext(S, DC); | 
| John McCall | 2408e32 | 2010-04-27 00:57:59 +0000 | [diff] [blame] | 830 |  | 
|  | 831 | // Rebuild the nested name specifier for the new scope. | 
|  | 832 | if (DC->isDependentContext()) | 
|  | 833 | RebuildNestedNameSpecifierInCurrentInstantiation(SS); | 
|  | 834 |  | 
| Douglas Gregor | 5013a7e | 2009-09-24 23:39:01 +0000 | [diff] [blame] | 835 | return false; | 
| Cedric Venet | 08438133 | 2009-02-14 20:20:19 +0000 | [diff] [blame] | 836 | } | 
|  | 837 |  | 
|  | 838 | /// ActOnCXXExitDeclaratorScope - Called when a declarator that previously | 
|  | 839 | /// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same | 
|  | 840 | /// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well. | 
|  | 841 | /// Used to indicate that names should revert to being looked up in the | 
|  | 842 | /// defining scope. | 
|  | 843 | void Sema::ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { | 
|  | 844 | assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); | 
| Douglas Gregor | 053f691 | 2009-08-26 00:04:55 +0000 | [diff] [blame] | 845 | if (SS.isInvalid()) | 
|  | 846 | return; | 
| John McCall | 6df5fef | 2009-12-19 10:49:29 +0000 | [diff] [blame] | 847 | assert(!SS.isInvalid() && computeDeclContext(SS, true) && | 
|  | 848 | "exiting declarator scope we never really entered"); | 
|  | 849 | ExitDeclaratorContext(S); | 
| Cedric Venet | 08438133 | 2009-02-14 20:20:19 +0000 | [diff] [blame] | 850 | } |