Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Recover from missing 'typename' in sizeof(T::InnerType)
Summary: 'sizeof' is a UnaryExprOrTypeTrait, and it can contain either a type or an expression. This change threads a RecoveryTSI parameter through the layers between TransformUnaryExprOrTypeTrait the point at which we look up the type. If lookup finds a single type result after instantiation, we now build TypeSourceInfo for it just like a normal transformation would. This fixes the last error in the hello world ATL app that I've been working with, and it now links and runs with clang. Please try it and file bugs! Reviewers: rsmith Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D4108 llvm-svn: 210855
- Loading branch information
Showing
7 changed files
with
165 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -verify %s | ||
|
||
// If we were even more clever, we'd tell the user to use one set of parens to | ||
// get the size of this type, so they don't get errors after inserting typename. | ||
|
||
namespace basic { | ||
template <typename T> int type_f() { return sizeof T::type; } // expected-error {{missing 'typename' prior to dependent type name 'X::type'}} | ||
template <typename T> int type_g() { return sizeof(T::type); } // expected-warning {{missing 'typename' prior to dependent type name 'X::type'}} | ||
template <typename T> int type_h() { return sizeof((T::type)); } // expected-error {{missing 'typename' prior to dependent type name 'X::type'}} | ||
template <typename T> int value_f() { return sizeof T::not_a_type; } | ||
template <typename T> int value_g() { return sizeof(T::not_a_type); } | ||
template <typename T> int value_h() { return sizeof((T::not_a_type)); } | ||
struct X { | ||
typedef int type; | ||
static const int not_a_type; | ||
}; | ||
int bar() { | ||
return | ||
type_f<X>() + // expected-note-re {{in instantiation {{.*}} requested here}} | ||
type_g<X>() + // expected-note-re {{in instantiation {{.*}} requested here}} | ||
type_h<X>() + // expected-note-re {{in instantiation {{.*}} requested here}} | ||
value_f<X>() + | ||
value_f<X>() + | ||
value_f<X>(); | ||
} | ||
} | ||
|
||
namespace nested_sizeof { | ||
template <typename T> | ||
struct Foo { | ||
enum { | ||
// expected-warning@+2 {{use 'template' keyword to treat 'InnerTemplate' as a dependent template name}} | ||
// expected-warning@+1 {{missing 'typename' prior to dependent type name 'Bar::InnerType'}} | ||
x1 = sizeof(typename T::/*template*/ InnerTemplate<sizeof(/*typename*/ T::InnerType)>), | ||
// expected-warning@+1 {{missing 'typename' prior to dependent type name 'Bar::InnerType'}} | ||
x2 = sizeof(typename T::template InnerTemplate<sizeof(/*typename*/ T::InnerType)>), | ||
// expected-warning@+1 {{use 'template' keyword to treat 'InnerTemplate' as a dependent template name}} | ||
y1 = sizeof(typename T::/*template*/ InnerTemplate<sizeof(T::InnerVar)>), | ||
y2 = sizeof(typename T::template InnerTemplate<sizeof(T::InnerVar)>), | ||
z = sizeof(T::template InnerTemplate<sizeof(T::InnerVar)>::x), | ||
}; | ||
}; | ||
struct Bar { | ||
template <int N> | ||
struct InnerTemplate { int x[N]; }; | ||
typedef double InnerType; | ||
static const int InnerVar = 42; | ||
}; | ||
template struct Foo<Bar>; // expected-note-re {{in instantiation {{.*}} requested here}} | ||
} | ||
|
||
namespace ambiguous_missing_parens { | ||
// expected-error@+1 {{'Q::U' instantiated to a class template, not a function template}} | ||
template <typename T> void f() { int a = sizeof T::template U<0> + 4; } | ||
struct Q { | ||
// expected-error@+1 {{class template declared here}} | ||
template <int> struct U {}; | ||
}; | ||
// expected-note-re@+1 {{in instantiation {{.*}} requested here}} | ||
template void f<Q>(); | ||
} |