Merge remote-tracking branch 'origin/swift-4.1-branch' into stable
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 08b34a7..54e6ebc 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -1666,8 +1666,7 @@
unsigned HasSkippedBody : 1;
/// Indicates if the function declaration will have a body, once we're done
- /// parsing it. (We don't set it to false when we're done parsing, in the
- /// hopes this is simpler.)
+ /// parsing it.
unsigned WillHaveBody : 1;
/// \brief End part of this FunctionDecl's source range.
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 5cab488..1caceab 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -1837,9 +1837,10 @@
const FunctionDecl *CheckFn = getTemplateInstantiationPattern();
if (!CheckFn)
CheckFn = this;
-
+
const FunctionDecl *fn;
- return CheckFn->hasBody(fn) && !fn->isOutOfLine();
+ return CheckFn->isDefined(fn) && !fn->isOutOfLine() &&
+ (fn->doesThisDeclarationHaveABody() || fn->willHaveBody());
}
bool CXXMethodDecl::isLambdaStaticInvoker() const {
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index 00ce398..32724c4 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -167,20 +167,11 @@
}
if (FnD) {
- // If this is a friend function, mark that it's late-parsed so that
- // it's still known to be a definition even before we attach the
- // parsed body. Sema needs to treat friend function definitions
- // differently during template instantiation, and it's possible for
- // the containing class to be instantiated before all its member
- // function definitions are parsed.
- //
- // If you remove this, you can remove the code that clears the flag
- // after parsing the member.
- if (D.getDeclSpec().isFriendSpecified()) {
- FunctionDecl *FD = FnD->getAsFunction();
- Actions.CheckForFunctionRedefinition(FD);
- FD->setLateTemplateParsed(true);
- }
+ FunctionDecl *FD = FnD->getAsFunction();
+ // Track that this function will eventually have a body; Sema needs
+ // to know this.
+ Actions.CheckForFunctionRedefinition(FD);
+ FD->setWillHaveBody(true);
} else {
// If semantic analysis could not build a function declaration,
// just throw away the late-parsed declaration.
@@ -559,10 +550,6 @@
ParseFunctionStatementBody(LM.D, FnScope);
- // Clear the late-template-parsed bit if we set it before.
- if (LM.D)
- LM.D->getAsFunction()->setLateTemplateParsed(false);
-
while (Tok.isNot(tok::eof))
ConsumeAnyToken();
diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp
index 7b9e1ba..ad63486 100644
--- a/lib/Sema/SemaCast.cpp
+++ b/lib/Sema/SemaCast.cpp
@@ -552,7 +552,14 @@
Qualifiers SrcQuals, DestQuals;
Self.Context.getUnqualifiedArrayType(UnwrappedSrcType, SrcQuals);
Self.Context.getUnqualifiedArrayType(UnwrappedDestType, DestQuals);
-
+
+ // We do not meaningfully track object const-ness of Objective-C object
+ // types. Remove const from the source type if either the source or
+ // the destination is an Objective-C object type.
+ if (UnwrappedSrcType->isObjCObjectType() ||
+ UnwrappedDestType->isObjCObjectType())
+ SrcQuals.removeConst();
+
Qualifiers RetainedSrcQuals, RetainedDestQuals;
if (CheckCVR) {
RetainedSrcQuals.setCVRQualifiers(SrcQuals.getCVRQualifiers());
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index b76ef4f..21bce0a 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -12104,8 +12104,9 @@
FD->setInvalidDecl();
}
- // See if this is a redefinition.
- if (!FD->isLateTemplateParsed()) {
+ // See if this is a redefinition. If 'will have body' is already set, then
+ // these checks were already performed when it was set.
+ if (!FD->willHaveBody() && !FD->isLateTemplateParsed()) {
CheckForFunctionRedefinition(FD, nullptr, SkipBody);
// If we're skipping the body, we're done. Don't enter the scope.
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index abe912f..6fee23a 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3771,6 +3771,8 @@
if (PatternDef) {
Pattern = PatternDef->getBody(PatternDef);
PatternDecl = PatternDef;
+ if (PatternDef->willHaveBody())
+ PatternDef = nullptr;
}
// FIXME: We need to track the instantiation stack in order to know which
diff --git a/test/CodeGenCXX/pr34163.cpp b/test/CodeGenCXX/pr34163.cpp
new file mode 100644
index 0000000..a200a0f
--- /dev/null
+++ b/test/CodeGenCXX/pr34163.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -triple x86_64-linux-gnu -o - -x c++ %s | FileCheck %s
+
+void f(struct X *) {}
+
+// CHECK: @_ZTV1X =
+struct X {
+ void a() { delete this; }
+ virtual ~X() {}
+ virtual void key_function();
+};
+
+// CHECK: define {{.*}} @_ZN1X12key_functionEv(
+void X::key_function() {}
diff --git a/test/SemaCUDA/function-overload.cu b/test/SemaCUDA/function-overload.cu
index 3d4c29c..adf488b 100644
--- a/test/SemaCUDA/function-overload.cu
+++ b/test/SemaCUDA/function-overload.cu
@@ -222,7 +222,7 @@
// Test overloading of destructors
// Can't mix H and unattributed destructors
struct d_h {
- ~d_h() {} // expected-note {{previous declaration is here}}
+ ~d_h() {} // expected-note {{previous definition is here}}
__host__ ~d_h() {} // expected-error {{destructor cannot be redeclared}}
};
diff --git a/test/SemaCUDA/no-destructor-overload.cu b/test/SemaCUDA/no-destructor-overload.cu
index aa6971e..32dbb8d 100644
--- a/test/SemaCUDA/no-destructor-overload.cu
+++ b/test/SemaCUDA/no-destructor-overload.cu
@@ -7,27 +7,27 @@
// giant change to clang, and the use cases seem quite limited.
struct A {
- ~A() {} // expected-note {{previous declaration is here}}
+ ~A() {} // expected-note {{previous definition is here}}
__device__ ~A() {} // expected-error {{destructor cannot be redeclared}}
};
struct B {
- __host__ ~B() {} // expected-note {{previous declaration is here}}
+ __host__ ~B() {} // expected-note {{previous definition is here}}
__host__ __device__ ~B() {} // expected-error {{destructor cannot be redeclared}}
};
struct C {
- __host__ __device__ ~C() {} // expected-note {{previous declaration is here}}
+ __host__ __device__ ~C() {} // expected-note {{previous definition is here}}
__host__ ~C() {} // expected-error {{destructor cannot be redeclared}}
};
struct D {
- __device__ ~D() {} // expected-note {{previous declaration is here}}
+ __device__ ~D() {} // expected-note {{previous definition is here}}
__host__ __device__ ~D() {} // expected-error {{destructor cannot be redeclared}}
};
struct E {
- __host__ __device__ ~E() {} // expected-note {{previous declaration is here}}
+ __host__ __device__ ~E() {} // expected-note {{previous definition is here}}
__device__ ~E() {} // expected-error {{destructor cannot be redeclared}}
};
diff --git a/test/SemaObjC/illegal-nonarc-bridged-cast.m b/test/SemaObjC/illegal-nonarc-bridged-cast.m
index f3406ef..23c7b96 100644
--- a/test/SemaObjC/illegal-nonarc-bridged-cast.m
+++ b/test/SemaObjC/illegal-nonarc-bridged-cast.m
@@ -1,8 +1,9 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fsyntax-only -fblocks -verify %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fsyntax-only -fblocks -Wcast-qual -verify %s
// rdar://10597832
typedef const void *CFTypeRef;
typedef const struct __CFString *CFStringRef;
+@class NSString;
@interface NSString
@end
@@ -18,7 +19,7 @@
void from_cf() {
id obj1 = (__bridge_transfer id)CFCreateSomething(); // expected-warning {{'__bridge_transfer' casts have no effect when not using ARC}}
id obj2 = (__bridge_transfer NSString*)CFCreateString(); // expected-warning {{'__bridge_transfer' casts have no effect when not using ARC}}
- (__bridge int*)CFCreateSomething(); // expected-warning {{expression result unused}}
+ (__bridge int*)CFCreateSomething(); // expected-warning {{expression result unused}} expected-warning {{cast from 'const void *' to 'int *' drops const qualifier}}
id obj3 = (__bridge id)CFGetSomething();
id obj4 = (__bridge NSString*)CFGetString();
}
@@ -41,3 +42,15 @@
CFTypeRef cf1 = (__bridge_retained CFTypeRef)CreateSomething(); // no-warning
CFTypeRef cf3 = (__bridge CFTypeRef)CreateSomething(); // no-warning
}
+
+// Check that clang doesn't warn about dropping const from Objective-C object
+// types.
+void test_wcast_qual() {
+ CFStringRef c;
+ NSString *n0 = (NSString *)c;
+ NSString **n1 = (NSString **)&c;
+ const NSString *n2;
+ const NSString **n3;
+ void *p0 = (void *)n2;
+ void **p1 = (void **)n3;
+}