aboutsummaryrefslogtreecommitdiff
path: root/clang
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2019-08-16 08:11:28 +0000
committerHans Wennborg <hans@hanshq.net>2019-08-16 08:11:28 +0000
commit150ad3120e346ed8dff2bdda458a72e734b1879a (patch)
treec9cddf95ebb6983c692436413485c0231c37f619 /clang
parentb77d4716f4b211d15f874c779598ee26460eb091 (diff)
downloadllvm-150ad3120e346ed8dff2bdda458a72e734b1879a.zip
llvm-150ad3120e346ed8dff2bdda458a72e734b1879a.tar.gz
llvm-150ad3120e346ed8dff2bdda458a72e734b1879a.tar.bz2
Merging r368940:
------------------------------------------------------------------------ r368940 | rsmith | 2019-08-15 00:57:50 +0200 (Thu, 15 Aug 2019) | 19 lines Fix handling of class member access into a vector type. When handling a member access into a non-class, non-ObjC-object type, we would perform a lookup into the surrounding scope as if for an unqualified lookup. If the member access was followed by a '<' and this lookup (or the typo-correction for it) found a template name, we'd treat the member access as naming that template. Now we treat such accesses as never naming a template if the type of the object expression is of vector type, so that vector component accesses are never misinterpreted as naming something else. This is not entirely correct, since it is in fact valid to name a template from the enclosing scope in this context, when invoking a pseudo-destructor for the vector type via an alias template, but that's very much a corner case, and this change leaves that case only as broken as the corresponding case for Objective-C types is. This incidentally adds support for dr2292, which permits a 'template' keyword at the start of a member access naming a pseudo-destructor. ------------------------------------------------------------------------ llvm-svn: 369087
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp6
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp20
-rw-r--r--clang/test/CXX/drs/dr22xx.cpp9
-rw-r--r--clang/test/CXX/drs/dr4xx.cpp4
-rw-r--r--clang/test/SemaCXX/cxx2a-adl-only-template-id.cpp8
-rw-r--r--clang/test/SemaCXX/pseudo-destructors.cpp4
-rw-r--r--clang/test/SemaCXX/vector.cpp16
7 files changed, 55 insertions, 12 deletions
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 705e3b9..c1c0896 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/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/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 3212281..ec4b63a 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/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/clang/test/CXX/drs/dr22xx.cpp b/clang/test/CXX/drs/dr22xx.cpp
index 70a26db..8896281 100644
--- a/clang/test/CXX/drs/dr22xx.cpp
+++ b/clang/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/clang/test/CXX/drs/dr4xx.cpp b/clang/test/CXX/drs/dr4xx.cpp
index 00393cc2..8eeb771 100644
--- a/clang/test/CXX/drs/dr4xx.cpp
+++ b/clang/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/clang/test/SemaCXX/cxx2a-adl-only-template-id.cpp b/clang/test/SemaCXX/cxx2a-adl-only-template-id.cpp
index 4bd9a22..28ecbad 100644
--- a/clang/test/SemaCXX/cxx2a-adl-only-template-id.cpp
+++ b/clang/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/clang/test/SemaCXX/pseudo-destructors.cpp b/clang/test/SemaCXX/pseudo-destructors.cpp
index 08938bf..fb2d0af 100644
--- a/clang/test/SemaCXX/pseudo-destructors.cpp
+++ b/clang/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/clang/test/SemaCXX/vector.cpp b/clang/test/SemaCXX/vector.cpp
index 40dcd35..295e1e1 100644
--- a/clang/test/SemaCXX/vector.cpp
+++ b/clang/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'
+ }
+}