[cfe-commits] r147281 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaCXX/typedef-redecl.cpp
Rafael Espindola
rafael.espindola at gmail.com
Mon Dec 26 14:42:47 PST 2011
Author: rafael
Date: Mon Dec 26 16:42:47 2011
New Revision: 147281
URL: http://llvm.org/viewvc/llvm-project?rev=147281&view=rev
Log:
Delay checking of typedefs of dependent types. Fixes PR11630.
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/SemaCXX/typedef-redecl.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=147281&r1=147280&r2=147281&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Dec 26 16:42:47 2011
@@ -1326,6 +1326,7 @@
/// Subroutines of ActOnDeclarator().
TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
TypeSourceInfo *TInfo);
+ bool isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New);
void MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls);
bool MergeFunctionDecl(FunctionDecl *New, Decl *Old);
bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old);
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=147281&r1=147280&r2=147281&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Dec 26 16:42:47 2011
@@ -1368,6 +1368,30 @@
return New;
}
+bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) {
+ QualType OldType;
+ if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old))
+ OldType = OldTypedef->getUnderlyingType();
+ else
+ OldType = Context.getTypeDeclType(Old);
+ QualType NewType = New->getUnderlyingType();
+
+ if (OldType != NewType &&
+ !OldType->isDependentType() &&
+ !NewType->isDependentType() &&
+ Context.getCanonicalType(OldType) !=
+ Context.getCanonicalType(NewType)) {
+ int Kind = isa<TypeAliasDecl>(Old) ? 1 : 0;
+ Diag(New->getLocation(), diag::err_redefinition_different_typedef)
+ << Kind << NewType << OldType;
+ if (Old->getLocation().isValid())
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ New->setInvalidDecl();
+ return true;
+ }
+ return false;
+}
+
/// MergeTypedefNameDecl - We just parsed a typedef 'New' which has the
/// same name and scope as a previous declaration 'Old'. Figure out
/// how to resolve this situation, merging decls or emitting
@@ -1426,28 +1450,10 @@
if (Old->isInvalidDecl())
return New->setInvalidDecl();
- // Determine the "old" type we'll use for checking and diagnostics.
- QualType OldType;
- if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old))
- OldType = OldTypedef->getUnderlyingType();
- else
- OldType = Context.getTypeDeclType(Old);
-
// If the typedef types are not identical, reject them in all languages and
// with any extensions enabled.
-
- if (OldType != New->getUnderlyingType() &&
- Context.getCanonicalType(OldType) !=
- Context.getCanonicalType(New->getUnderlyingType())) {
- int Kind = 0;
- if (isa<TypeAliasDecl>(Old))
- Kind = 1;
- Diag(New->getLocation(), diag::err_redefinition_different_typedef)
- << Kind << New->getUnderlyingType() << OldType;
- if (Old->getLocation().isValid())
- Diag(Old->getLocation(), diag::note_previous_definition);
- return New->setInvalidDecl();
- }
+ if (isIncompatibleTypedef(Old, New))
+ return;
// The types match. Link up the redeclaration chain if the old
// declaration was a typedef.
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=147281&r1=147280&r2=147281&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Dec 26 16:42:47 2011
@@ -169,7 +169,12 @@
if (!InstPrev)
return 0;
- Typedef->setPreviousDeclaration(cast<TypedefNameDecl>(InstPrev));
+ TypedefNameDecl *InstPrevTypedef = cast<TypedefNameDecl>(InstPrev);
+
+ // If the typedef types are not identical, reject them.
+ SemaRef.isIncompatibleTypedef(InstPrevTypedef, Typedef);
+
+ Typedef->setPreviousDeclaration(InstPrevTypedef);
}
SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef);
Modified: cfe/trunk/test/SemaCXX/typedef-redecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/typedef-redecl.cpp?rev=147281&r1=147280&r2=147281&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/typedef-redecl.cpp (original)
+++ cfe/trunk/test/SemaCXX/typedef-redecl.cpp Mon Dec 26 16:42:47 2011
@@ -59,3 +59,37 @@
typedef T f(T t) { return t; } // expected-error {{function definition declared 'typedef'}}
int k = f(0);
int k2 = k;
+
+namespace PR11630 {
+ template <class T>
+ struct S
+ {
+ static const unsigned C = 1;
+ static void f()
+ {
+ typedef int q[C == 1 ? 1 : -1]; // expected-note{{previous definition is here}}
+ typedef int q[C >= 1 ? 2 : -2]; // expected-error{{typedef redefinition with different types ('int [2]' vs 'int [1]')}}
+ typedef int n[C == 1 ? 1 : -1];
+ typedef int n[C >= 1 ? 1 : -1];
+ }
+ };
+
+ template <int T>
+ struct S2
+ {
+ static void f()
+ {
+ typedef int q[1]; // expected-note{{previous definition is here}}
+ typedef int q[T]; // expected-error{{typedef redefinition with different types ('int [2]' vs 'int [1]')}}
+ }
+ };
+
+ void f() {
+ S<int> a;
+ a.f(); // expected-note{{in instantiation of member function 'PR11630::S<int>::f' requested here}}
+ S2<1> b;
+ b.f();
+ S2<2> b2;
+ b2.f(); // expected-note{{in instantiation of member function 'PR11630::S2<2>::f' requested here}}
+ }
+}
More information about the cfe-commits
mailing list