r230301 - [modules] Ensure we've imported all declarations of a template before
Richard Smith
richard-llvm at metafoo.co.uk
Mon Feb 23 18:44:23 PST 2015
Author: rsmith
Date: Mon Feb 23 20:44:23 2015
New Revision: 230301
URL: http://llvm.org/viewvc/llvm-project?rev=230301&view=rev
Log:
[modules] Ensure we've imported all declarations of a template before
attempting to lazily deserialize its specializations; otherwise, there might be
pending specializations that we don't know about yet.
Added:
cfe/trunk/test/Modules/Inputs/redecl-templates/
cfe/trunk/test/Modules/Inputs/redecl-templates/a.h
cfe/trunk/test/Modules/Inputs/redecl-templates/module.modulemap
cfe/trunk/test/Modules/redecl-templates.cpp
Modified:
cfe/trunk/include/clang/AST/DeclTemplate.h
cfe/trunk/lib/AST/DeclTemplate.cpp
Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=230301&r1=230300&r2=230301&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Mon Feb 23 20:44:23 2015
@@ -835,6 +835,15 @@ public:
static_cast<const RedeclarableTemplateDecl *>(this)->getPreviousDecl());
}
+ FunctionTemplateDecl *getMostRecentDecl() {
+ return cast<FunctionTemplateDecl>(
+ static_cast<RedeclarableTemplateDecl *>(this)
+ ->getMostRecentDecl());
+ }
+ const FunctionTemplateDecl *getMostRecentDecl() const {
+ return const_cast<FunctionTemplateDecl*>(this)->getMostRecentDecl();
+ }
+
FunctionTemplateDecl *getInstantiatedFromMemberTemplate() {
return cast_or_null<FunctionTemplateDecl>(
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
@@ -2731,6 +2740,14 @@ public:
this)->getPreviousDecl());
}
+ VarTemplateDecl *getMostRecentDecl() {
+ return cast<VarTemplateDecl>(
+ static_cast<RedeclarableTemplateDecl *>(this)->getMostRecentDecl());
+ }
+ const VarTemplateDecl *getMostRecentDecl() const {
+ return const_cast<VarTemplateDecl *>(this)->getMostRecentDecl();
+ }
+
VarTemplateDecl *getInstantiatedFromMemberTemplate() {
return cast_or_null<VarTemplateDecl>(
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=230301&r1=230300&r2=230301&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Mon Feb 23 20:44:23 2015
@@ -272,7 +272,11 @@ FunctionTemplateDecl::newCommon(ASTConte
}
void FunctionTemplateDecl::LoadLazySpecializations() const {
- Common *CommonPtr = getCommonPtr();
+ // Grab the most recent declaration to ensure we've loaded any lazy
+ // redeclarations of this template.
+ //
+ // FIXME: Avoid walking the entire redeclaration chain here.
+ Common *CommonPtr = getMostRecentDecl()->getCommonPtr();
if (CommonPtr->LazySpecializations) {
ASTContext &Context = getASTContext();
uint32_t *Specs = CommonPtr->LazySpecializations;
@@ -342,7 +346,11 @@ ClassTemplateDecl *ClassTemplateDecl::Cr
}
void ClassTemplateDecl::LoadLazySpecializations() const {
- Common *CommonPtr = getCommonPtr();
+ // Grab the most recent declaration to ensure we've loaded any lazy
+ // redeclarations of this template.
+ //
+ // FIXME: Avoid walking the entire redeclaration chain here.
+ Common *CommonPtr = getMostRecentDecl()->getCommonPtr();
if (CommonPtr->LazySpecializations) {
ASTContext &Context = getASTContext();
uint32_t *Specs = CommonPtr->LazySpecializations;
@@ -966,7 +974,11 @@ VarTemplateDecl *VarTemplateDecl::Create
// TODO: Unify across class, function and variable templates?
// May require moving this and Common to RedeclarableTemplateDecl.
void VarTemplateDecl::LoadLazySpecializations() const {
- Common *CommonPtr = getCommonPtr();
+ // Grab the most recent declaration to ensure we've loaded any lazy
+ // redeclarations of this template.
+ //
+ // FIXME: Avoid walking the entire redeclaration chain here.
+ Common *CommonPtr = getMostRecentDecl()->getCommonPtr();
if (CommonPtr->LazySpecializations) {
ASTContext &Context = getASTContext();
uint32_t *Specs = CommonPtr->LazySpecializations;
Added: cfe/trunk/test/Modules/Inputs/redecl-templates/a.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/redecl-templates/a.h?rev=230301&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/redecl-templates/a.h (added)
+++ cfe/trunk/test/Modules/Inputs/redecl-templates/a.h Mon Feb 23 20:44:23 2015
@@ -0,0 +1,8 @@
+template<int N> struct A;
+template<> struct A<1>;
+
+template<int N> constexpr void f();
+template<> constexpr void f<1>();
+
+template<int N> extern int v;
+template<> extern int v<1>;
Added: cfe/trunk/test/Modules/Inputs/redecl-templates/module.modulemap
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/redecl-templates/module.modulemap?rev=230301&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/redecl-templates/module.modulemap (added)
+++ cfe/trunk/test/Modules/Inputs/redecl-templates/module.modulemap Mon Feb 23 20:44:23 2015
@@ -0,0 +1 @@
+module A { header "a.h" }
Added: cfe/trunk/test/Modules/redecl-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/redecl-templates.cpp?rev=230301&view=auto
==============================================================================
--- cfe/trunk/test/Modules/redecl-templates.cpp (added)
+++ cfe/trunk/test/Modules/redecl-templates.cpp Mon Feb 23 20:44:23 2015
@@ -0,0 +1,32 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -x c++ -I %S/Inputs/redecl-templates %s -verify -std=c++14
+// RUN: %clang_cc1 -x c++ -fmodules -fmodules-cache-path=%t -I %S/Inputs/redecl-templates %s -verify -std=c++14
+// expected-no-diagnostics
+
+template<int N> struct A {};
+template<int N> using X = A<N>;
+
+template<int N> constexpr void f() {}
+template<int N> constexpr void g() { f<N>(); }
+
+template<int N> extern int v;
+template<int N> int &w = v<N>;
+
+#include "a.h"
+
+// Be careful not to mention A here, that'll import the decls from "a.h".
+int g(X<1> *);
+X<1> *p = 0;
+
+// This will implicitly instantiate A<1> if we haven't imported the explicit
+// specialization declaration from "a.h".
+int k = g(p);
+// Likewise for f and v.
+void h() { g<1>(); }
+int &x = w<1>;
+
+// This is OK: we declared the explicit specialization before we triggered
+// instantiation of this specialization.
+template<> struct A<1> {};
+template<> constexpr void f<1>() {}
+template<> int v<1>;
More information about the cfe-commits
mailing list