diff options
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 20 | ||||
-rw-r--r-- | test/CXX/drs/dr22xx.cpp | 9 | ||||
-rw-r--r-- | test/CXX/drs/dr4xx.cpp | 4 | ||||
-rw-r--r-- | test/SemaCXX/cxx2a-adl-only-template-id.cpp | 8 | ||||
-rw-r--r-- | test/SemaCXX/pseudo-destructors.cpp | 4 | ||||
-rw-r--r-- | test/SemaCXX/vector.cpp | 16 |
7 files changed, 55 insertions, 12 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 8f882e4ca3..7c68e4d914 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -6794,14 +6794,10 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, // it's legal for the type to be incomplete if this is a pseudo-destructor // call. We'll do more incomplete-type checks later in the lookup process, // so just skip this check for ObjC types. - if (BaseType->isObjCObjectOrInterfaceType()) { + if (!BaseType->isRecordType()) { ObjectType = ParsedType::make(BaseType); MayBePseudoDestructor = true; return Base; - } else if (!BaseType->isRecordType()) { - ObjectType = nullptr; - MayBePseudoDestructor = true; - return Base; } // The object type must be complete (or dependent), or diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 3df74edf2f..ce0c2ef402 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -362,13 +362,27 @@ bool Sema::LookupTemplateName(LookupResult &Found, // x->B::f, and we are looking into the type of the object. assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist"); LookupCtx = computeDeclContext(ObjectType); - IsDependent = !LookupCtx; + IsDependent = !LookupCtx && ObjectType->isDependentType(); assert((IsDependent || !ObjectType->isIncompleteType() || ObjectType->castAs<TagType>()->isBeingDefined()) && "Caller should have completed object type"); - // Template names cannot appear inside an Objective-C class or object type. - if (ObjectType->isObjCObjectOrInterfaceType()) { + // Template names cannot appear inside an Objective-C class or object type + // or a vector type. + // + // FIXME: This is wrong. For example: + // + // template<typename T> using Vec = T __attribute__((ext_vector_type(4))); + // Vec<int> vi; + // vi.Vec<int>::~Vec<int>(); + // + // ... should be accepted but we will not treat 'Vec' as a template name + // here. The right thing to do would be to check if the name is a valid + // vector component name, and look up a template name if not. And similarly + // for lookups into Objective-C class and object types, where the same + // problem can arise. + if (ObjectType->isObjCObjectOrInterfaceType() || + ObjectType->isVectorType()) { Found.clear(); return false; } diff --git a/test/CXX/drs/dr22xx.cpp b/test/CXX/drs/dr22xx.cpp index 70a26db757..8896281e9c 100644 --- a/test/CXX/drs/dr22xx.cpp +++ b/test/CXX/drs/dr22xx.cpp @@ -26,3 +26,12 @@ void f() { } } #endif + +namespace dr2292 { // dr2292: 9 +#if __cplusplus >= 201103L + template<typename T> using id = T; + void test(int *p) { + p->template id<int>::~id<int>(); + } +#endif +} diff --git a/test/CXX/drs/dr4xx.cpp b/test/CXX/drs/dr4xx.cpp index 00393cc2e4..8eeb7715ca 100644 --- a/test/CXX/drs/dr4xx.cpp +++ b/test/CXX/drs/dr4xx.cpp @@ -318,8 +318,8 @@ namespace dr420 { // dr420: yes q->~id<int>(); p->id<int>::~id<int>(); q->id<int>::~id<int>(); - p->template id<int>::~id<int>(); // expected-error {{'template' keyword not permitted here}} expected-error {{base type 'int' is not a struct}} - q->template id<int>::~id<int>(); // expected-error {{'template' keyword not permitted here}} expected-error {{base type 'int' is not a struct}} + p->template id<int>::~id<int>(); // OK since dr2292 + q->template id<int>::~id<int>(); // OK since dr2292 p->A::template id<int>::~id<int>(); q->A::template id<int>::~id<int>(); } diff --git a/test/SemaCXX/cxx2a-adl-only-template-id.cpp b/test/SemaCXX/cxx2a-adl-only-template-id.cpp index 4bd9a22f5f..28ecbade1b 100644 --- a/test/SemaCXX/cxx2a-adl-only-template-id.cpp +++ b/test/SemaCXX/cxx2a-adl-only-template-id.cpp @@ -65,3 +65,11 @@ void xf(g<int> x); // expected-error {{variable has incomplete type 'void'}} exp struct B : g<int> { // expected-error {{expected class name}} B() : g<int>() {} // expected-error {{expected class member or base class name}} }; + +namespace vector_components { + typedef __attribute__((__ext_vector_type__(2))) float vector_float2; + bool foo123(vector_float2 &A, vector_float2 &B) + { + return A.x < B.x && B.y > A.y; + } +} diff --git a/test/SemaCXX/pseudo-destructors.cpp b/test/SemaCXX/pseudo-destructors.cpp index 08938bf34a..fb2d0afdc3 100644 --- a/test/SemaCXX/pseudo-destructors.cpp +++ b/test/SemaCXX/pseudo-destructors.cpp @@ -34,7 +34,7 @@ void f(A* a, Foo *f, int *i, double *d, int ii) { g().~Bar(); // expected-error{{non-scalar}} f->::~Bar(); - f->N::~Wibble(); // FIXME: technically, Wibble isn't a class-name + f->N::~Wibble(); // expected-error{{'N' does not refer to a type}} expected-error{{'Wibble' does not refer to a type}} f->::~Bar(17, 42); // expected-error{{cannot have any arguments}} @@ -79,7 +79,7 @@ namespace PR11339 { template<class T> void destroy(T* p) { p->~T(); // ok - p->~oops(); // expected-error{{expected the class name after '~' to name a destructor}} + p->~oops(); // expected-error{{identifier 'oops' in object destruction expression does not name a type}} } template void destroy(int*); // expected-note{{in instantiation of function template specialization}} diff --git a/test/SemaCXX/vector.cpp b/test/SemaCXX/vector.cpp index 40dcd35c1b..295e1e1732 100644 --- a/test/SemaCXX/vector.cpp +++ b/test/SemaCXX/vector.cpp @@ -342,3 +342,19 @@ void test_vector_literal(inte4 res) { inte4 b = (inte4)(a, a); //expected-error{{C-style cast from vector 'inte2' (vector of 2 'int' values) to vector 'inte4' (vector of 4 'int' values) of different size}} //expected-warning{{expression result unused}} } +typedef __attribute__((__ext_vector_type__(4))) float vector_float4; +typedef __attribute__((__ext_vector_type__(4))) int vector_int4; + +namespace swizzle_template_confusion { + template<typename T> struct xyzw {}; + vector_int4 foo123(vector_float4 &A, vector_float4 &B) { + return A.xyzw < B.x && B.y > A.y; // OK, not a template-id + } +} + +namespace swizzle_typo_correction { + template<typename T> struct xyzv {}; + vector_int4 foo123(vector_float4 &A, vector_float4 &B) { + return A.xyzw < B.x && B.y > A.y; // OK, not a typo for 'xyzv' + } +} |