summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaExprCXX.cpp6
-rw-r--r--lib/Sema/SemaTemplate.cpp20
-rw-r--r--test/CXX/drs/dr22xx.cpp9
-rw-r--r--test/CXX/drs/dr4xx.cpp4
-rw-r--r--test/SemaCXX/cxx2a-adl-only-template-id.cpp8
-rw-r--r--test/SemaCXX/pseudo-destructors.cpp4
-rw-r--r--test/SemaCXX/vector.cpp16
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'
+ }
+}