diff options
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 17 | ||||
| -rw-r--r-- | clang/lib/Sema/TreeTransform.h | 78 | 
3 files changed, 85 insertions, 14 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 4c101ad2b85..832a75848e4 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -5408,7 +5408,7 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,    //    // FIXME: handle "template <> friend class A<T>;", which    // is possibly well-formed?  Who even knows? -  if (TempParams.size() && !isa<ElaboratedType>(T)) { +  if (TempParams.size() && !T->isElaboratedTypeSpecifier()) {      Diag(Loc, diag::err_tagless_friend_type_template)        << DS.getSourceRange();      return DeclPtrTy(); @@ -5420,7 +5420,7 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,    //   * The class-key of the elaborated-type-specifier is required.    // This is one of the rare places in Clang where it's legitimate to    // ask about the "spelling" of the type. -  if (!getLangOptions().CPlusPlus0x && !isa<ElaboratedType>(T)) { +  if (!getLangOptions().CPlusPlus0x && !T->isElaboratedTypeSpecifier()) {      // If we evaluated the type to a record type, suggest putting      // a tag in front.      if (const RecordType *RT = T->getAs<RecordType>()) { diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index e3533905fd3..8e93fd876ed 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4915,14 +4915,15 @@ Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,    if (!NNS)      return true; -  QualType T = CheckTypenameType(NNS, *Name, SourceRange(TagLoc, NameLoc)); -  if (T.isNull()) -    return true; - -  TagDecl::TagKind TagKind = TagDecl::getTagKindForTypeSpec(TagSpec); -  QualType ElabType = Context.getElaboratedType(T, TagKind); - -  return ElabType.getAsOpaquePtr(); +  ElaboratedTypeKeyword Keyword; +  switch (TagDecl::getTagKindForTypeSpec(TagSpec)) { +  case TagDecl::TK_struct: Keyword = ETK_Struct; break; +  case TagDecl::TK_class: Keyword = ETK_Class; break; +  case TagDecl::TK_union: Keyword = ETK_Union; break; +  case TagDecl::TK_enum: Keyword = ETK_Enum; break; +  } +   +  return Context.getDependentNameType(Keyword, NNS, Name).getAsOpaquePtr();  }  Sema::TypeResult diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index a2ace07576c..b08447e4805 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -537,19 +537,21 @@ public:    /// \brief Build a new typename type that refers to a template-id.    /// -  /// By default, builds a new DependentNameType type from the nested-name-specifier +  /// By default, builds a new DependentNameType type from the  +  /// nested-name-specifier    /// and the given type. Subclasses may override this routine to provide    /// different behavior.    QualType RebuildDependentNameType(ElaboratedTypeKeyword Keyword,                                      NestedNameSpecifier *NNS, QualType T) {      if (NNS->isDependent()) { +      // If the name is still dependent, just build a new dependent name type.        CXXScopeSpec SS;        SS.setScopeRep(NNS);        if (!SemaRef.computeDeclContext(SS))          return SemaRef.Context.getDependentNameType(Keyword, NNS,                                            cast<TemplateSpecializationType>(T));      } - +          // FIXME: Handle elaborated-type-specifiers separately.      return SemaRef.Context.getQualifiedNameType(NNS, T);    } @@ -563,8 +565,76 @@ public:                                      NestedNameSpecifier *NNS,                                      const IdentifierInfo *Id,                                      SourceRange SR) { -    // FIXME: Handle elaborated-type-specifiers separately. -    return SemaRef.CheckTypenameType(NNS, *Id, SR); +    CXXScopeSpec SS; +    SS.setScopeRep(NNS); +     +    if (NNS->isDependent()) { +      // If the name is still dependent, just build a new dependent name type. +      if (!SemaRef.computeDeclContext(SS)) +        return SemaRef.Context.getDependentNameType(Keyword, NNS, Id); +    } + +    TagDecl::TagKind Kind = TagDecl::TK_enum; +    switch (Keyword) { +      case ETK_None: +        // FIXME: Note the lack of the "typename" specifier! +        // Fall through +      case ETK_Typename: +        return SemaRef.CheckTypenameType(NNS, *Id, SR); +         +      case ETK_Class: Kind = TagDecl::TK_class; break; +      case ETK_Struct: Kind = TagDecl::TK_struct; break; +      case ETK_Union: Kind = TagDecl::TK_union; break; +      case ETK_Enum: Kind = TagDecl::TK_enum; break; +    } +     +    // We had a dependent elaborated-type-specifier that as been transformed +    // into a non-dependent elaborated-type-specifier. Find the tag we're +    // referring to. +    LookupResult Result(SemaRef, Id, SR.getEnd(), Sema::LookupTagName); +    DeclContext *DC = SemaRef.computeDeclContext(SS, false); +    if (!DC) +      return QualType(); + +    TagDecl *Tag = 0; +    SemaRef.LookupQualifiedName(Result, DC); +    switch (Result.getResultKind()) { +      case LookupResult::NotFound: +      case LookupResult::NotFoundInCurrentInstantiation: +        break; +         +      case LookupResult::Found: +        Tag = Result.getAsSingle<TagDecl>(); +        break; +         +      case LookupResult::FoundOverloaded: +      case LookupResult::FoundUnresolvedValue: +        llvm_unreachable("Tag lookup cannot find non-tags"); +        return QualType(); +         +      case LookupResult::Ambiguous: +        // Let the LookupResult structure handle ambiguities. +        return QualType(); +    } + +    if (!Tag) { +      // FIXME: Crummy diagnostic +      SemaRef.Diag(SR.getEnd(), diag::err_not_tag_in_scope) +        << Id << SR; +      return QualType(); +    } +     +    // FIXME: Terrible location information +    if (!SemaRef.isAcceptableTagRedeclaration(Tag, Kind, SR.getEnd(), *Id)) { +      SemaRef.Diag(SR.getBegin(), diag::err_use_with_wrong_tag) << Id; +      SemaRef.Diag(Tag->getLocation(), diag::note_previous_use); +      return QualType(); +    } + +    // Build the elaborated-type-specifier type. +    QualType T = SemaRef.Context.getTypeDeclType(Tag); +    T = SemaRef.Context.getQualifiedNameType(NNS, T); +    return SemaRef.Context.getElaboratedType(T, Kind);    }    /// \brief Build a new nested-name-specifier given the prefix and an  | 

