r224898 - Sema: Don't crash when an inject class name has a nested redefinition
David Majnemer
david.majnemer at gmail.com
Sun Dec 28 01:18:54 PST 2014
Author: majnemer
Date: Sun Dec 28 03:18:54 2014
New Revision: 224898
URL: http://llvm.org/viewvc/llvm-project?rev=224898&view=rev
Log:
Sema: Don't crash when an inject class name has a nested redefinition
We expected the type of a TagDecl to be a TagType, not an
InjectedClassNameType. Introduced a helper method, Type::getAsTagDecl,
to abstract away the difference; redefine Type::getAsCXXRecordDecl to be
in terms of it.
Modified:
cfe/trunk/include/clang/AST/Type.h
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/SemaCXX/struct-class-redecl.cpp
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=224898&r1=224897&r2=224898&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Sun Dec 28 03:18:54 2014
@@ -1707,6 +1707,11 @@ public:
/// type of a class template or class template partial specialization.
CXXRecordDecl *getAsCXXRecordDecl() const;
+ /// \brief Retrieves the TagDecl that this type refers to, either
+ /// because the type is a TagType or because it is the injected-class-name
+ /// type of a class template or class template partial specialization.
+ TagDecl *getAsTagDecl() const;
+
/// If this is a pointer or reference to a RecordType, return the
/// CXXRecordDecl that that type refers to.
///
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=224898&r1=224897&r2=224898&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Sun Dec 28 03:18:54 2014
@@ -541,10 +541,13 @@ const CXXRecordDecl *Type::getPointeeCXX
}
CXXRecordDecl *Type::getAsCXXRecordDecl() const {
- if (const RecordType *RT = getAs<RecordType>())
- return dyn_cast<CXXRecordDecl>(RT->getDecl());
- else if (const InjectedClassNameType *Injected
- = getAs<InjectedClassNameType>())
+ return dyn_cast_or_null<CXXRecordDecl>(getAsTagDecl());
+}
+
+TagDecl *Type::getAsTagDecl() const {
+ if (const auto *TT = getAs<TagType>())
+ return cast<TagDecl>(TT->getDecl());
+ if (const auto *Injected = getAs<InjectedClassNameType>())
return Injected->getDecl();
return nullptr;
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=224898&r1=224897&r2=224898&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun Dec 28 03:18:54 2014
@@ -11599,9 +11599,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned
} else {
// If the type is currently being defined, complain
// about a nested redefinition.
- const TagType *Tag
- = cast<TagType>(Context.getTagDeclType(PrevTagDecl));
- if (Tag->isBeingDefined()) {
+ auto *TD = Context.getTagDeclType(PrevTagDecl)->getAsTagDecl();
+ if (TD->isBeingDefined()) {
Diag(NameLoc, diag::err_nested_redefinition) << Name;
Diag(PrevTagDecl->getLocation(),
diag::note_previous_definition);
Modified: cfe/trunk/test/SemaCXX/struct-class-redecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/struct-class-redecl.cpp?rev=224898&r1=224897&r2=224898&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/struct-class-redecl.cpp (original)
+++ cfe/trunk/test/SemaCXX/struct-class-redecl.cpp Sun Dec 28 03:18:54 2014
@@ -7,6 +7,12 @@ union X { int x; float y; }; // expected
template<typename T> struct Y; // expected-note{{did you mean class here?}}
template<class U> class Y { }; // expected-warning{{previously declared}}
+template <typename>
+struct Z { // expected-note{{previous definition is here}}
+ struct Z { // expected-error{{nested redefinition of 'Z'}}
+ };
+};
+
class A;
class A; // expected-note{{previous use is here}}
struct A; // expected-warning{{struct 'A' was previously declared as a class}}
More information about the cfe-commits
mailing list