[cfe-commits] r70784 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplate.cpp test/SemaCXX/struct-class-redecl.cpp test/SemaCXX/typedef-redecl.cpp test/SemaTemplate/class-template-decl.cpp
Douglas Gregor
dgregor at apple.com
Sun May 3 10:18:57 PDT 2009
Author: dgregor
Date: Sun May 3 12:18:57 2009
New Revision: 70784
URL: http://llvm.org/viewvc/llvm-project?rev=70784&view=rev
Log:
One can use "class" and "struct" interchangeably to refer to a class
in C++. Fixes <rdar://problem/6815995>.
Added:
cfe/trunk/test/SemaCXX/struct-class-redecl.cpp (with props)
Modified:
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/SemaCXX/typedef-redecl.cpp
cfe/trunk/test/SemaTemplate/class-template-decl.cpp
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=70784&r1=70783&r2=70784&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sun May 3 12:18:57 2009
@@ -429,6 +429,33 @@
virtual DeclPtrTy BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
RecordDecl *Record);
+ /// \brief Determine whether a tag with a given kind is acceptable
+ /// for a redeclaration of a tag type declared with another tag.
+ ///
+ /// \p T1 and \p T2 are the tag kinds. Since the rules for
+ /// redeclaration of tags are symmetric, it does not matter which is
+ /// the previous declaration and which is the new declaration.
+ bool isAcceptableTagRedeclaration(TagDecl::TagKind T1, TagDecl::TagKind T2) {
+ // C++ [dcl.type.elab]p3:
+ // The class-key ore num keyword present in the
+ // elaborated-type-specifier shall agree in kind with the
+ // declaration to which the name in theelaborated-type-specifier
+ // refers. This rule also applies to the form of
+ // elaborated-type-specifier that declares a class-name or
+ // friend class since it can be construed as referring to the
+ // definition of the class. Thus, in any
+ // elaborated-type-specifier, the enum keyword shall be used to
+ // refer to an enumeration (7.2), the union class-keyshall be
+ // used to refer to a union (clause 9), and either the class or
+ // struct class-key shall be used to refer to a class (clause 9)
+ // declared using the class or struct class-key.
+ if (T1 == T2)
+ return true;
+
+ return (T1 == TagDecl::TK_struct || T1 == TagDecl::TK_class) &&
+ (T2 == TagDecl::TK_struct || T2 == TagDecl::TK_class);
+ }
+
virtual DeclPtrTy ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
SourceLocation KWLoc, const CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=70784&r1=70783&r2=70784&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun May 3 12:18:57 2009
@@ -3295,7 +3295,7 @@
if (TK == TK_Reference || isDeclInScope(PrevDecl, SearchDC, S)) {
// Make sure that this wasn't declared as an enum and now used as a
// struct or something similar.
- if (PrevTagDecl->getTagKind() != Kind) {
+ if (!isAcceptableTagRedeclaration(PrevTagDecl->getTagKind(), Kind)) {
bool SafeToContinue
= (PrevTagDecl->getTagKind() != TagDecl::TK_enum &&
Kind != TagDecl::TK_enum);
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=70784&r1=70783&r2=70784&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Sun May 3 12:18:57 2009
@@ -461,7 +461,7 @@
// the class-key shall agree in kind with the original class
// template declaration (7.1.5.3).
RecordDecl *PrevRecordDecl = PrevClassTemplate->getTemplatedDecl();
- if (PrevRecordDecl->getTagKind() != Kind) {
+ if (!isAcceptableTagRedeclaration(PrevRecordDecl->getTagKind(), Kind)) {
Diag(KWLoc, diag::err_use_with_wrong_tag)
<< Name
<< CodeModificationHint::CreateReplacement(KWLoc,
@@ -1975,7 +1975,9 @@
case DeclSpec::TST_union: Kind = TagDecl::TK_union; break;
case DeclSpec::TST_class: Kind = TagDecl::TK_class; break;
}
- if (ClassTemplate->getTemplatedDecl()->getTagKind() != Kind) {
+ if (!isAcceptableTagRedeclaration(
+ ClassTemplate->getTemplatedDecl()->getTagKind(),
+ Kind)) {
Diag(KWLoc, diag::err_use_with_wrong_tag)
<< ClassTemplate
<< CodeModificationHint::CreateReplacement(KWLoc,
Added: cfe/trunk/test/SemaCXX/struct-class-redecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/struct-class-redecl.cpp?rev=70784&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/struct-class-redecl.cpp (added)
+++ cfe/trunk/test/SemaCXX/struct-class-redecl.cpp Sun May 3 12:18:57 2009
@@ -0,0 +1,8 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+class X; // expected-note{{here}}
+typedef struct X * X_t;
+
+template<typename T> class Y;
+template<class U> struct Y { };
+
+union X { int x; float y; }; // expected-error{{use of 'X' with tag type that does not match previous declaration}}
Propchange: cfe/trunk/test/SemaCXX/struct-class-redecl.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/SemaCXX/struct-class-redecl.cpp
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/SemaCXX/struct-class-redecl.cpp
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: cfe/trunk/test/SemaCXX/typedef-redecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/typedef-redecl.cpp?rev=70784&r1=70783&r2=70784&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/typedef-redecl.cpp (original)
+++ cfe/trunk/test/SemaCXX/typedef-redecl.cpp Sun May 3 12:18:57 2009
@@ -29,5 +29,3 @@
struct s { };
-typedef class st { /* ... */ } st; // expected-note{{previous use is here}}
-struct st; // expected-error{{use of 'st' with tag type that does not match previous declaration}}
Modified: cfe/trunk/test/SemaTemplate/class-template-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/class-template-decl.cpp?rev=70784&r1=70783&r2=70784&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/class-template-decl.cpp (original)
+++ cfe/trunk/test/SemaTemplate/class-template-decl.cpp Sun May 3 12:18:57 2009
@@ -14,13 +14,10 @@
template<typename T> class D; // expected-error{{templates must have C++ linkage}}
}
-template<class U> class A; // expected-note{{previous template declaration is here}}\
- // expected-note{{previous use is here}}
+template<class U> class A; // expected-note{{previous template declaration is here}}
template<int N> class A; // expected-error{{template parameter has a different kind in template redeclaration}}
-template<class T> struct A; // expected-error{{use of 'A' with tag type that does not match previous declaration}}
-
template<int N> class NonTypeTemplateParm;
typedef int INT;
More information about the cfe-commits
mailing list