forked from qt-creator/qt-creator
Clang: Require LLVM/Clang >= 6.0.0
Adapt versions and tests, remove code assuming clang < 6.0. Switch also to our custom repositories instead of dealing with patch files. LLVM/Clang 6 was released on 09 Mar 2018. Task-number: QTCREATORBUG-18535 Task-number: QTCREATORBUG-18552 Change-Id: I0ec2c2f56265e161ae7cbb5b03e7b8a182ba6cc6 Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
This commit is contained in:
19
README.md
19
README.md
@@ -22,7 +22,7 @@ Prerequisites:
|
|||||||
* jom
|
* jom
|
||||||
* On Mac OS X: latest Xcode
|
* On Mac OS X: latest Xcode
|
||||||
* On Linux: g++ 4.9 or later
|
* On Linux: g++ 4.9 or later
|
||||||
* LLVM/Clang 5.0.0 or later (optional, needed for the Clang Code Model, see the
|
* LLVM/Clang 6.0.0 or later (optional, needed for the Clang Code Model, see the
|
||||||
section "Get LLVM/Clang for the Clang Code Model")
|
section "Get LLVM/Clang for the Clang Code Model")
|
||||||
* CMake (only for manual builds of LLVM/Clang)
|
* CMake (only for manual builds of LLVM/Clang)
|
||||||
* Qbs 1.7.x (optional, sources also contain Qbs itself)
|
* Qbs 1.7.x (optional, sources also contain Qbs itself)
|
||||||
@@ -206,7 +206,7 @@ or using shadow builds.
|
|||||||
## Get LLVM/Clang for the Clang Code Model
|
## Get LLVM/Clang for the Clang Code Model
|
||||||
|
|
||||||
The Clang Code Model depends on the LLVM/Clang libraries. The currently
|
The Clang Code Model depends on the LLVM/Clang libraries. The currently
|
||||||
supported LLVM/Clang version is 5.0.
|
supported LLVM/Clang version is 6.0.
|
||||||
|
|
||||||
### Prebuilt LLVM/Clang packages
|
### Prebuilt LLVM/Clang packages
|
||||||
|
|
||||||
@@ -233,9 +233,9 @@ GCC 4 binaries. On Ubuntu, you can download the package from
|
|||||||
http://apt.llvm.org/ with:
|
http://apt.llvm.org/ with:
|
||||||
|
|
||||||
wget -O - http://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
wget -O - http://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||||
sudo apt-add-repository "deb http://apt.llvm.org/`lsb_release -cs`/ llvm-toolchain-`lsb_release -cs`-5.0 main"
|
sudo apt-add-repository "deb http://apt.llvm.org/`lsb_release -cs`/ llvm-toolchain-`lsb_release -cs`-6.0 main"
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install llvm-5.0 libclang-5.0-dev
|
sudo apt-get install llvm-6.0 libclang-6.0-dev
|
||||||
|
|
||||||
There is a workaround to set _GLIBCXX_USE_CXX11_ABI to 1 or 0, but we recommend
|
There is a workaround to set _GLIBCXX_USE_CXX11_ABI to 1 or 0, but we recommend
|
||||||
to download the package from http://apt.llvm.org/.
|
to download the package from http://apt.llvm.org/.
|
||||||
@@ -251,11 +251,11 @@ http://llvm.org/docs/GettingStarted.html#git-mirror:
|
|||||||
|
|
||||||
1. Clone LLVM and checkout a suitable branch
|
1. Clone LLVM and checkout a suitable branch
|
||||||
|
|
||||||
git clone -b release_50 https://git.llvm.org/git/llvm
|
git clone -b release_60-based git://code.qt.io/clang/llvm.git
|
||||||
|
|
||||||
2. Clone Clang into llvm/tools/clang and checkout a suitable branch
|
2. Clone Clang into llvm/tools/clang and checkout a suitable branch
|
||||||
|
|
||||||
git clone -b release_50 https://git.llvm.org/git/clang llvm/tools/clang
|
git clone -b release_60-based git://code.qt.io/clang/clang.git llvm/tools/clang
|
||||||
|
|
||||||
3. Build and install LLVM/Clang
|
3. Build and install LLVM/Clang
|
||||||
|
|
||||||
@@ -285,7 +285,8 @@ we thank the authors who made this possible:
|
|||||||
|
|
||||||
Distributed under GNU LIBRARY GENERAL PUBLIC LICENSE Version 2 (LGPL2).
|
Distributed under GNU LIBRARY GENERAL PUBLIC LICENSE Version 2 (LGPL2).
|
||||||
|
|
||||||
Integrated with patches from QtCreator/dist/clang/patches, see README.md there.
|
Integrated with patches from
|
||||||
|
http://code.qt.io/cgit/clang/clang-tools-extra.git/.
|
||||||
|
|
||||||
### LLVM/Clang
|
### LLVM/Clang
|
||||||
|
|
||||||
@@ -298,7 +299,9 @@ we thank the authors who made this possible:
|
|||||||
Distributed under the University of Illinois/NCSA Open Source License (NCSA),
|
Distributed under the University of Illinois/NCSA Open Source License (NCSA),
|
||||||
see https://github.com/llvm-mirror/llvm/blob/master/LICENSE.TXT
|
see https://github.com/llvm-mirror/llvm/blob/master/LICENSE.TXT
|
||||||
|
|
||||||
With additional patches from QtCreator/dist/clang/patches, see README.md there.
|
With backported/additional patches from
|
||||||
|
http://code.qt.io/cgit/clang/llvm.git/
|
||||||
|
http://code.qt.io/cgit/clang/clang.git/
|
||||||
|
|
||||||
### Reference implementation for std::experimental::optional
|
### Reference implementation for std::experimental::optional
|
||||||
|
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
diff --git a/tools/clang/lib/Frontend/ASTUnit.cpp b/tools/clang/lib/Frontend/ASTUnit.cpp
|
|
||||||
index 1094e6d089..5a4cddbebe 100644
|
|
||||||
--- a/tools/clang/lib/Frontend/ASTUnit.cpp
|
|
||||||
+++ b/tools/clang/lib/Frontend/ASTUnit.cpp
|
|
||||||
@@ -243,7 +243,8 @@ static unsigned getDeclShowContexts(const NamedDecl *ND,
|
|
||||||
|
|
||||||
uint64_t Contexts = 0;
|
|
||||||
if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) ||
|
|
||||||
- isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND)) {
|
|
||||||
+ isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND) ||
|
|
||||||
+ isa<TypeAliasTemplateDecl>(ND)) {
|
|
||||||
// Types can appear in these contexts.
|
|
||||||
if (LangOpts.CPlusPlus || !isa<TagDecl>(ND))
|
|
||||||
Contexts |= (1LL << CodeCompletionContext::CCC_TopLevel)
|
|
||||||
diff --git a/tools/clang/lib/Parse/ParseTemplate.cpp b/tools/clang/lib/Parse/ParseTemplate.cpp
|
|
||||||
index 944cd775d5..6aba10e5c7 100644
|
|
||||||
--- a/tools/clang/lib/Parse/ParseTemplate.cpp
|
|
||||||
+++ b/tools/clang/lib/Parse/ParseTemplate.cpp
|
|
||||||
@@ -198,9 +198,11 @@ Parser::ParseSingleDeclarationAfterTemplate(
|
|
||||||
|
|
||||||
if (Tok.is(tok::kw_using)) {
|
|
||||||
// FIXME: We should return the DeclGroup to the caller.
|
|
||||||
- ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd,
|
|
||||||
- prefixAttrs);
|
|
||||||
- return nullptr;
|
|
||||||
+ auto usingDeclPtr = ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd,
|
|
||||||
+ prefixAttrs);
|
|
||||||
+ if (!usingDeclPtr || !usingDeclPtr.get().isSingleDecl())
|
|
||||||
+ return nullptr;
|
|
||||||
+ return usingDeclPtr.get().getSingleDecl();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the declaration specifiers, stealing any diagnostics from
|
|
||||||
@@ -1023,8 +1025,8 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
|
|
||||||
? OO_None
|
|
||||||
: TemplateName.OperatorFunctionId.Operator;
|
|
||||||
|
|
||||||
- TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Create(
|
|
||||||
- SS, TemplateKWLoc, TemplateNameLoc, TemplateII, OpKind, Template, TNK,
|
|
||||||
+ TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Create(
|
|
||||||
+ SS, TemplateKWLoc, TemplateNameLoc, TemplateII, OpKind, Template, TNK,
|
|
||||||
LAngleLoc, RAngleLoc, TemplateArgs, TemplateIds);
|
|
||||||
|
|
||||||
Tok.setAnnotationValue(TemplateId);
|
|
||||||
diff --git a/tools/clang/test/Index/code-completion.cpp b/tools/clang/test/Index/code-completion.cpp
|
|
||||||
index f52bb10a35..00f158f3d0 100644
|
|
||||||
--- a/tools/clang/test/Index/code-completion.cpp
|
|
||||||
+++ b/tools/clang/test/Index/code-completion.cpp
|
|
||||||
@@ -37,6 +37,16 @@ Z::operator int() const {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+template <typename T>
|
|
||||||
+struct Foo { T member; };
|
|
||||||
+
|
|
||||||
+template<typename T> using Bar = Foo<T>;
|
|
||||||
+
|
|
||||||
+void test_template_alias() {
|
|
||||||
+ // RUN: env CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:47:1 %s | FileCheck -check-prefix=CHECK-TEMPLATE-ALIAS %s
|
|
||||||
+
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
// CHECK-MEMBER: FieldDecl:{ResultType double}{TypedText member}
|
|
||||||
// CHECK-MEMBER: FieldDecl:{ResultType int}{Text X::}{TypedText member}
|
|
||||||
// CHECK-MEMBER: FieldDecl:{ResultType float}{Text Y::}{TypedText member}
|
|
||||||
@@ -88,3 +98,5 @@ Z::operator int() const {
|
|
||||||
// CHECK-EXPR-NEXT: Class name
|
|
||||||
// CHECK-EXPR-NEXT: Nested name specifier
|
|
||||||
// CHECK-EXPR-NEXT: Objective-C interface
|
|
||||||
+
|
|
||||||
+// CHECK-TEMPLATE-ALIAS: AliasTemplateDecl:{TypedText Bar}{LeftAngle <}{Placeholder typename T}{RightAngle >} (50)
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
diff --git a/tools/clang/lib/Sema/SemaCodeComplete.cpp b/tools/clang/lib/Sema/SemaCodeComplete.cpp
|
|
||||||
index 4de7d42207..7001849426 100644
|
|
||||||
--- a/tools/clang/lib/Sema/SemaCodeComplete.cpp
|
|
||||||
+++ b/tools/clang/lib/Sema/SemaCodeComplete.cpp
|
|
||||||
@@ -4286,9 +4286,12 @@ static void mergeCandidatesWithResults(Sema &SemaRef,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add the remaining viable overload candidates as code-completion results.
|
|
||||||
- for (auto &Candidate : CandidateSet)
|
|
||||||
+ for (auto &Candidate : CandidateSet) {
|
|
||||||
+ if (Candidate.Function && Candidate.Function->isDeleted())
|
|
||||||
+ continue;
|
|
||||||
if (Candidate.Viable)
|
|
||||||
Results.push_back(ResultCandidate(Candidate.Function));
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/tools/clang/test/Index/complete-constructor-params.cpp b/tools/clang/test/Index/complete-constructor-params.cpp
|
|
||||||
index 6685626a58..949077a214 100644
|
|
||||||
--- a/tools/clang/test/Index/complete-constructor-params.cpp
|
|
||||||
+++ b/tools/clang/test/Index/complete-constructor-params.cpp
|
|
||||||
@@ -18,6 +18,20 @@ int main() {
|
|
||||||
int(42);
|
|
||||||
}
|
|
||||||
|
|
||||||
+struct Foo {
|
|
||||||
+ Foo() = default;
|
|
||||||
+ Foo(const Foo&) = delete;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+struct Bar {
|
|
||||||
+ Foo f;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+void function() {
|
|
||||||
+ Bar b1;
|
|
||||||
+ Bar b2(b1);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
// RUN: c-index-test -code-completion-at=%s:11:10 %s | FileCheck -check-prefix=CHECK-CC1 %s
|
|
||||||
// CHECK-CC1: OverloadCandidate:{Text S}{LeftParen (}{CurrentParameter const S<int> &}{RightParen )} (1)
|
|
||||||
// CHECK-CC1: OverloadCandidate:{Text S}{LeftParen (}{CurrentParameter int}{Comma , }{Placeholder U}{Comma , }{Placeholder U}{RightParen )} (1)
|
|
||||||
@@ -138,3 +152,6 @@ int main() {
|
|
||||||
// CHECK-CC10-NEXT: Class name
|
|
||||||
// CHECK-CC10-NEXT: Nested name specifier
|
|
||||||
// CHECK-CC10-NEXT: Objective-C interface
|
|
||||||
+
|
|
||||||
+// RUN: c-index-test -code-completion-at=%s:32:12 -std=c++11 %s | FileCheck -check-prefix=CHECK-CC11 %s
|
|
||||||
+// CHECK-CC11-NOT: OverloadCandidate:{Text Bar}{LeftParen (}{CurrentParameter const Bar &}{RightParen )} (1)
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
--- /dev/null
|
|
||||||
+++ b/tools/clang/test/Index/annotate-tokens-unexposed.cpp
|
|
||||||
@@ -0,0 +1,20 @@
|
|
||||||
+// RUN: c-index-test -test-annotate-tokens=%s:1:1:16:1 %s -target x86_64-pc-windows-msvc | FileCheck %s
|
|
||||||
+class Foo
|
|
||||||
+{
|
|
||||||
+public:
|
|
||||||
+ void step(int v);
|
|
||||||
+ Foo();
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+void bar()
|
|
||||||
+{
|
|
||||||
+ // Introduce a MSInheritanceAttr node on the CXXRecordDecl for Foo. The
|
|
||||||
+ // existence of this attribute should not mark all cursors for tokens in
|
|
||||||
+ // Foo as UnexposedAttr.
|
|
||||||
+ &Foo::step;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+Foo::Foo()
|
|
||||||
+{}
|
|
||||||
+
|
|
||||||
+// CHECK-NOT: UnexposedAttr=
|
|
||||||
--- a/tools/clang/tools/libclang/CIndex.cpp
|
|
||||||
+++ b/tools/clang/tools/libclang/CIndex.cpp
|
|
||||||
@@ -1772,7 +1772,7 @@
|
|
||||||
|
|
||||||
bool CursorVisitor::VisitAttributes(Decl *D) {
|
|
||||||
for (const auto *I : D->attrs())
|
|
||||||
- if (Visit(MakeCXCursor(I, D, TU)))
|
|
||||||
+ if (!I->isImplicit() && Visit(MakeCXCursor(I, D, TU)))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
@@ -1,266 +0,0 @@
|
|||||||
--- a/tools/clang/lib/AST/DeclPrinter.cpp
|
|
||||||
+++ b/tools/clang/lib/AST/DeclPrinter.cpp
|
|
||||||
@@ -608,66 +608,69 @@
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CDecl) {
|
|
||||||
- bool HasInitializerList = false;
|
|
||||||
- for (const auto *BMInitializer : CDecl->inits()) {
|
|
||||||
- if (BMInitializer->isInClassMemberInitializer())
|
|
||||||
- continue;
|
|
||||||
-
|
|
||||||
- if (!HasInitializerList) {
|
|
||||||
- Proto += " : ";
|
|
||||||
- Out << Proto;
|
|
||||||
- Proto.clear();
|
|
||||||
- HasInitializerList = true;
|
|
||||||
- } else
|
|
||||||
- Out << ", ";
|
|
||||||
+ if (!Policy.TerseOutput) {
|
|
||||||
+ bool HasInitializerList = false;
|
|
||||||
+ for (const auto *BMInitializer : CDecl->inits()) {
|
|
||||||
+ if (BMInitializer->isInClassMemberInitializer())
|
|
||||||
+ continue;
|
|
||||||
|
|
||||||
- if (BMInitializer->isAnyMemberInitializer()) {
|
|
||||||
- FieldDecl *FD = BMInitializer->getAnyMember();
|
|
||||||
- Out << *FD;
|
|
||||||
- } else {
|
|
||||||
- Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy);
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- Out << "(";
|
|
||||||
- if (!BMInitializer->getInit()) {
|
|
||||||
- // Nothing to print
|
|
||||||
- } else {
|
|
||||||
- Expr *Init = BMInitializer->getInit();
|
|
||||||
- if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
|
|
||||||
- Init = Tmp->getSubExpr();
|
|
||||||
-
|
|
||||||
- Init = Init->IgnoreParens();
|
|
||||||
-
|
|
||||||
- Expr *SimpleInit = nullptr;
|
|
||||||
- Expr **Args = nullptr;
|
|
||||||
- unsigned NumArgs = 0;
|
|
||||||
- if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
|
|
||||||
- Args = ParenList->getExprs();
|
|
||||||
- NumArgs = ParenList->getNumExprs();
|
|
||||||
- } else if (CXXConstructExpr *Construct
|
|
||||||
- = dyn_cast<CXXConstructExpr>(Init)) {
|
|
||||||
- Args = Construct->getArgs();
|
|
||||||
- NumArgs = Construct->getNumArgs();
|
|
||||||
+ if (!HasInitializerList) {
|
|
||||||
+ Proto += " : ";
|
|
||||||
+ Out << Proto;
|
|
||||||
+ Proto.clear();
|
|
||||||
+ HasInitializerList = true;
|
|
||||||
} else
|
|
||||||
- SimpleInit = Init;
|
|
||||||
-
|
|
||||||
- if (SimpleInit)
|
|
||||||
- SimpleInit->printPretty(Out, nullptr, Policy, Indentation);
|
|
||||||
- else {
|
|
||||||
- for (unsigned I = 0; I != NumArgs; ++I) {
|
|
||||||
- assert(Args[I] != nullptr && "Expected non-null Expr");
|
|
||||||
- if (isa<CXXDefaultArgExpr>(Args[I]))
|
|
||||||
- break;
|
|
||||||
-
|
|
||||||
- if (I)
|
|
||||||
- Out << ", ";
|
|
||||||
- Args[I]->printPretty(Out, nullptr, Policy, Indentation);
|
|
||||||
+ Out << ", ";
|
|
||||||
+
|
|
||||||
+ if (BMInitializer->isAnyMemberInitializer()) {
|
|
||||||
+ FieldDecl *FD = BMInitializer->getAnyMember();
|
|
||||||
+ Out << *FD;
|
|
||||||
+ } else {
|
|
||||||
+ Out << QualType(BMInitializer->getBaseClass(), 0)
|
|
||||||
+ .getAsString(Policy);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ Out << "(";
|
|
||||||
+ if (!BMInitializer->getInit()) {
|
|
||||||
+ // Nothing to print
|
|
||||||
+ } else {
|
|
||||||
+ Expr *Init = BMInitializer->getInit();
|
|
||||||
+ if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
|
|
||||||
+ Init = Tmp->getSubExpr();
|
|
||||||
+
|
|
||||||
+ Init = Init->IgnoreParens();
|
|
||||||
+
|
|
||||||
+ Expr *SimpleInit = nullptr;
|
|
||||||
+ Expr **Args = nullptr;
|
|
||||||
+ unsigned NumArgs = 0;
|
|
||||||
+ if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
|
|
||||||
+ Args = ParenList->getExprs();
|
|
||||||
+ NumArgs = ParenList->getNumExprs();
|
|
||||||
+ } else if (CXXConstructExpr *Construct =
|
|
||||||
+ dyn_cast<CXXConstructExpr>(Init)) {
|
|
||||||
+ Args = Construct->getArgs();
|
|
||||||
+ NumArgs = Construct->getNumArgs();
|
|
||||||
+ } else
|
|
||||||
+ SimpleInit = Init;
|
|
||||||
+
|
|
||||||
+ if (SimpleInit)
|
|
||||||
+ SimpleInit->printPretty(Out, nullptr, Policy, Indentation);
|
|
||||||
+ else {
|
|
||||||
+ for (unsigned I = 0; I != NumArgs; ++I) {
|
|
||||||
+ assert(Args[I] != nullptr && "Expected non-null Expr");
|
|
||||||
+ if (isa<CXXDefaultArgExpr>(Args[I]))
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ if (I)
|
|
||||||
+ Out << ", ";
|
|
||||||
+ Args[I]->printPretty(Out, nullptr, Policy, Indentation);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+ Out << ")";
|
|
||||||
+ if (BMInitializer->isPackExpansion())
|
|
||||||
+ Out << "...";
|
|
||||||
}
|
|
||||||
- Out << ")";
|
|
||||||
- if (BMInitializer->isPackExpansion())
|
|
||||||
- Out << "...";
|
|
||||||
}
|
|
||||||
} else if (!ConversionDecl && !isa<CXXDestructorDecl>(D)) {
|
|
||||||
if (FT && FT->hasTrailingReturn()) {
|
|
||||||
@@ -712,7 +715,7 @@
|
|
||||||
if (D->getBody())
|
|
||||||
D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation);
|
|
||||||
} else {
|
|
||||||
- if (isa<CXXConstructorDecl>(*D))
|
|
||||||
+ if (!Policy.TerseOutput && isa<CXXConstructorDecl>(*D))
|
|
||||||
Out << " {}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
--- a/tools/clang/test/Index/comment-cplus-decls.cpp
|
|
||||||
+++ b/tools/clang/test/Index/comment-cplus-decls.cpp
|
|
||||||
@@ -46,7 +46,7 @@
|
|
||||||
data* reserved;
|
|
||||||
};
|
|
||||||
// CHECK: <Declaration>class Test {}</Declaration>
|
|
||||||
-// CHECK: <Declaration>Test() : reserved(new Test::data()) {}</Declaration>
|
|
||||||
+// CHECK: <Declaration>Test()</Declaration>
|
|
||||||
// CHECK: <Declaration>unsigned int getID() const</Declaration>
|
|
||||||
// CHECK: <Declaration>~Test(){{( noexcept)?}}</Declaration>
|
|
||||||
// CHECK: <Declaration>Test::data *reserved</Declaration>
|
|
||||||
--- a/tools/clang/unittests/AST/DeclPrinterTest.cpp
|
|
||||||
+++ b/tools/clang/unittests/AST/DeclPrinterTest.cpp
|
|
||||||
@@ -31,18 +31,25 @@
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
-void PrintDecl(raw_ostream &Out, const ASTContext *Context, const Decl *D) {
|
|
||||||
+using PrintingPolicyModifier = void (*)(PrintingPolicy &policy);
|
|
||||||
+
|
|
||||||
+void PrintDecl(raw_ostream &Out, const ASTContext *Context, const Decl *D,
|
|
||||||
+ PrintingPolicyModifier PolicyModifier) {
|
|
||||||
PrintingPolicy Policy = Context->getPrintingPolicy();
|
|
||||||
Policy.TerseOutput = true;
|
|
||||||
+ if (PolicyModifier)
|
|
||||||
+ PolicyModifier(Policy);
|
|
||||||
D->print(Out, Policy, /*Indentation*/ 0, /*PrintInstantiation*/ false);
|
|
||||||
}
|
|
||||||
|
|
||||||
class PrintMatch : public MatchFinder::MatchCallback {
|
|
||||||
SmallString<1024> Printed;
|
|
||||||
unsigned NumFoundDecls;
|
|
||||||
+ PrintingPolicyModifier PolicyModifier;
|
|
||||||
|
|
||||||
public:
|
|
||||||
- PrintMatch() : NumFoundDecls(0) {}
|
|
||||||
+ PrintMatch(PrintingPolicyModifier PolicyModifier)
|
|
||||||
+ : NumFoundDecls(0), PolicyModifier(PolicyModifier) {}
|
|
||||||
|
|
||||||
void run(const MatchFinder::MatchResult &Result) override {
|
|
||||||
const Decl *D = Result.Nodes.getNodeAs<Decl>("id");
|
|
||||||
@@ -53,7 +60,7 @@
|
|
||||||
return;
|
|
||||||
|
|
||||||
llvm::raw_svector_ostream Out(Printed);
|
|
||||||
- PrintDecl(Out, Result.Context, D);
|
|
||||||
+ PrintDecl(Out, Result.Context, D, PolicyModifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
StringRef getPrinted() const {
|
|
||||||
@@ -65,13 +72,12 @@
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
-::testing::AssertionResult PrintedDeclMatches(
|
|
||||||
- StringRef Code,
|
|
||||||
- const std::vector<std::string> &Args,
|
|
||||||
- const DeclarationMatcher &NodeMatch,
|
|
||||||
- StringRef ExpectedPrinted,
|
|
||||||
- StringRef FileName) {
|
|
||||||
- PrintMatch Printer;
|
|
||||||
+::testing::AssertionResult
|
|
||||||
+PrintedDeclMatches(StringRef Code, const std::vector<std::string> &Args,
|
|
||||||
+ const DeclarationMatcher &NodeMatch,
|
|
||||||
+ StringRef ExpectedPrinted, StringRef FileName,
|
|
||||||
+ PrintingPolicyModifier PolicyModifier = nullptr) {
|
|
||||||
+ PrintMatch Printer(PolicyModifier);
|
|
||||||
MatchFinder Finder;
|
|
||||||
Finder.addMatcher(NodeMatch, &Printer);
|
|
||||||
std::unique_ptr<FrontendActionFactory> Factory(
|
|
||||||
@@ -109,16 +115,17 @@
|
|
||||||
"input.cc");
|
|
||||||
}
|
|
||||||
|
|
||||||
-::testing::AssertionResult PrintedDeclCXX98Matches(
|
|
||||||
- StringRef Code,
|
|
||||||
- const DeclarationMatcher &NodeMatch,
|
|
||||||
- StringRef ExpectedPrinted) {
|
|
||||||
+::testing::AssertionResult
|
|
||||||
+PrintedDeclCXX98Matches(StringRef Code, const DeclarationMatcher &NodeMatch,
|
|
||||||
+ StringRef ExpectedPrinted,
|
|
||||||
+ PrintingPolicyModifier PolicyModifier = nullptr) {
|
|
||||||
std::vector<std::string> Args(1, "-std=c++98");
|
|
||||||
return PrintedDeclMatches(Code,
|
|
||||||
Args,
|
|
||||||
NodeMatch,
|
|
||||||
ExpectedPrinted,
|
|
||||||
- "input.cc");
|
|
||||||
+ "input.cc",
|
|
||||||
+ PolicyModifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
::testing::AssertionResult PrintedDeclCXX11Matches(StringRef Code,
|
|
||||||
@@ -478,6 +485,27 @@
|
|
||||||
"A(const A &a, int = 0)"));
|
|
||||||
}
|
|
||||||
|
|
||||||
+TEST(DeclPrinter, TestCXXConstructorDeclWithMemberInitializer) {
|
|
||||||
+ ASSERT_TRUE(PrintedDeclCXX98Matches(
|
|
||||||
+ "struct A {"
|
|
||||||
+ " int m;"
|
|
||||||
+ " A() : m(2) {}"
|
|
||||||
+ "};",
|
|
||||||
+ cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
|
|
||||||
+ "A()"));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+TEST(DeclPrinter, TestCXXConstructorDeclWithMemberInitializer_NoTerseOutput) {
|
|
||||||
+ ASSERT_TRUE(PrintedDeclCXX98Matches(
|
|
||||||
+ "struct A {"
|
|
||||||
+ " int m;"
|
|
||||||
+ " A() : m(2) {}"
|
|
||||||
+ "};",
|
|
||||||
+ cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
|
|
||||||
+ "A() : m(2) {\n}\n",
|
|
||||||
+ [](PrintingPolicy &Policy){ Policy.TerseOutput = false; }));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
TEST(DeclPrinter, TestCXXConstructorDecl5) {
|
|
||||||
ASSERT_TRUE(PrintedDeclCXX11Matches(
|
|
||||||
"struct A {"
|
|
||||||
@@ -540,7 +568,7 @@
|
|
||||||
" A(T&&... ts) : T(ts)... {}"
|
|
||||||
"};",
|
|
||||||
cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
|
|
||||||
- "A<T...>(T &&...ts) : T(ts)... {}"));
|
|
||||||
+ "A<T...>(T &&...ts)"));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(DeclPrinter, TestCXXDestructorDecl1) {
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
--- a/tools/clang/test/Index/get-cursor.cpp
|
|
||||||
+++ b/tools/clang/test/Index/get-cursor.cpp
|
|
||||||
@@ -152,6 +152,11 @@
|
|
||||||
void f_dynamic_noexcept() throw(int);
|
|
||||||
void f_dynamic_noexcept_any() throw(...);
|
|
||||||
|
|
||||||
+enum EnumType { Enumerator };
|
|
||||||
+struct Z {
|
|
||||||
+ EnumType e = Enumerator;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
// RUN: c-index-test -cursor-at=%s:6:4 %s | FileCheck -check-prefix=CHECK-COMPLETION-1 %s
|
|
||||||
// CHECK-COMPLETION-1: CXXConstructor=X:6:3
|
|
||||||
// CHECK-COMPLETION-1-NEXT: Completion string: {TypedText X}{LeftParen (}{Placeholder int}{Comma , }{Placeholder int}{RightParen )}
|
|
||||||
@@ -275,3 +280,6 @@
|
|
||||||
// CHECK-FORRANGE: 141:18 DeclRefExpr=coll:140:20 Extent=[141:18 - 141:22] Spelling=coll ([141:18 - 141:22])
|
|
||||||
// CHECK-FORRANGE: 142:11 DeclRefExpr=lv:141:13 Extent=[142:11 - 142:13] Spelling=lv ([142:11 - 142:13])
|
|
||||||
|
|
||||||
+// RUN: c-index-test -cursor-at=%s:157:18 -std=c++11 %s | FileCheck -check-prefix=CHECK-INCLASSINITIALIZER %s
|
|
||||||
+// CHECK-INCLASSINITIALIZER: 157:18 DeclRefExpr=Enumerator:155:17 Extent=[157:18 - 157:28] Spelling=Enumerator ([157:18 - 157:28])
|
|
||||||
+
|
|
||||||
--- a/tools/clang/tools/libclang/CIndex.cpp
|
|
||||||
+++ b/tools/clang/tools/libclang/CIndex.cpp
|
|
||||||
@@ -877,6 +877,9 @@
|
|
||||||
if (Expr *BitWidth = D->getBitWidth())
|
|
||||||
return Visit(MakeCXCursor(BitWidth, StmtParent, TU, RegionOfInterest));
|
|
||||||
|
|
||||||
+ if (Expr *Init = D->getInClassInitializer())
|
|
||||||
+ return Visit(MakeCXCursor(Init, StmtParent, TU, RegionOfInterest));
|
|
||||||
+
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,154 +0,0 @@
|
|||||||
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
|
|
||||||
index 3b5ea9fa53..f2397d1b63 100644
|
|
||||||
--- a/tools/clang/include/clang-c/Index.h
|
|
||||||
+++ b/tools/clang/include/clang-c/Index.h
|
|
||||||
@@ -33,6 +33,7 @@
|
|
||||||
*/
|
|
||||||
#define CINDEX_VERSION_MAJOR 0
|
|
||||||
#define CINDEX_VERSION_MINOR 43
|
|
||||||
+#define CINDEX_VERSION_HAS_ISINVALIDECL_BACKPORTED
|
|
||||||
|
|
||||||
#define CINDEX_VERSION_ENCODE(major, minor) ( \
|
|
||||||
((major) * 10000) \
|
|
||||||
@@ -2616,6 +2617,16 @@ CINDEX_LINKAGE enum CXCursorKind clang_getCursorKind(CXCursor);
|
|
||||||
*/
|
|
||||||
CINDEX_LINKAGE unsigned clang_isDeclaration(enum CXCursorKind);
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * \brief Determine whether the given declaration is invalid.
|
|
||||||
+ *
|
|
||||||
+ * A declaration is invalid if it could not be parsed successfully.
|
|
||||||
+ *
|
|
||||||
+ * \returns non-zero if the cursor represents a declaration and it is
|
|
||||||
+ * invalid, otherwise NULL.
|
|
||||||
+ */
|
|
||||||
+CINDEX_LINKAGE unsigned clang_isInvalidDeclaration(CXCursor);
|
|
||||||
+
|
|
||||||
/**
|
|
||||||
* \brief Determine whether the given cursor kind represents a simple
|
|
||||||
* reference.
|
|
||||||
diff --git a/test/Index/opencl-types.cl b/test/Index/opencl-types.cl
|
|
||||||
index fe0042aa20..d71893a220 100644
|
|
||||||
--- a/tools/clang/test/Index/opencl-types.cl
|
|
||||||
+++ b/tools/clang/test/Index/opencl-types.cl
|
|
||||||
@@ -16,11 +16,11 @@ void kernel testFloatTypes() {
|
|
||||||
double4 vectorDouble;
|
|
||||||
}
|
|
||||||
|
|
||||||
-// CHECK: VarDecl=scalarHalf:11:8 (Definition) [type=half] [typekind=Half] [isPOD=1]
|
|
||||||
+// CHECK: VarDecl=scalarHalf:11:8 (Definition){{( \(invalid\))?}} [type=half] [typekind=Half] [isPOD=1]
|
|
||||||
// CHECK: VarDecl=vectorHalf:12:9 (Definition) [type=half4] [typekind=Typedef] [canonicaltype=half __attribute__((ext_vector_type(4)))] [canonicaltypekind=Unexposed] [isPOD=1]
|
|
||||||
// CHECK: VarDecl=scalarFloat:13:9 (Definition) [type=float] [typekind=Float] [isPOD=1]
|
|
||||||
// CHECK: VarDecl=vectorFloat:14:10 (Definition) [type=float4] [typekind=Typedef] [canonicaltype=float __attribute__((ext_vector_type(4)))] [canonicaltypekind=Unexposed] [isPOD=1]
|
|
||||||
-// CHECK: VarDecl=scalarDouble:15:10 (Definition) [type=double] [typekind=Double] [isPOD=1]
|
|
||||||
+// CHECK: VarDecl=scalarDouble:15:10 (Definition){{( \(invalid\))?}} [type=double] [typekind=Double] [isPOD=1]
|
|
||||||
// CHECK: VarDecl=vectorDouble:16:11 (Definition) [type=double4] [typekind=Typedef] [canonicaltype=double __attribute__((ext_vector_type(4)))] [canonicaltypekind=Unexposed] [isPOD=1]
|
|
||||||
|
|
||||||
#pragma OPENCL EXTENSION cl_khr_gl_msaa_sharing : enable
|
|
||||||
@@ -45,10 +45,10 @@ void kernel OCLImage3dROTest(read_only image3d_t scalarOCLImage3dRO);
|
|
||||||
// CHECK: ParmDecl=scalarOCLImage2dArrayRO:32:61 (Definition) [type=__read_only image2d_array_t] [typekind=OCLImage2dArrayRO] [isPOD=1]
|
|
||||||
// CHECK: ParmDecl=scalarOCLImage2dDepthRO:33:61 (Definition) [type=__read_only image2d_depth_t] [typekind=OCLImage2dDepthRO] [isPOD=1]
|
|
||||||
// CHECK: ParmDecl=scalarOCLImage2dArrayDepthRO:34:72 (Definition) [type=__read_only image2d_array_depth_t] [typekind=OCLImage2dArrayDepthRO] [isPOD=1]
|
|
||||||
-// CHECK: ParmDecl=scalarOCLImage2dMSAARO:35:59 (Definition) [type=__read_only image2d_msaa_t] [typekind=OCLImage2dMSAARO] [isPOD=1]
|
|
||||||
-// CHECK: ParmDecl=scalarOCLImage2dArrayMSAARO:36:70 (Definition) [type=__read_only image2d_array_msaa_t] [typekind=OCLImage2dArrayMSAARO] [isPOD=1]
|
|
||||||
-// CHECK: ParmDecl=scalarOCLImage2dMSAADepthRO:37:70 (Definition) [type=__read_only image2d_msaa_depth_t] [typekind=OCLImage2dMSAADepthRO] [isPOD=1]
|
|
||||||
-// CHECK: ParmDecl=scalarOCLImage2dArrayMSAADepthRO:38:81 (Definition) [type=__read_only image2d_array_msaa_depth_t] [typekind=OCLImage2dArrayMSAADepthRO] [isPOD=1]
|
|
||||||
+// CHECK: ParmDecl=scalarOCLImage2dMSAARO:35:59 (Definition){{( \(invalid\))?}} [type=__read_only image2d_msaa_t] [typekind=OCLImage2dMSAARO] [isPOD=1]
|
|
||||||
+// CHECK: ParmDecl=scalarOCLImage2dArrayMSAARO:36:70 (Definition){{( \(invalid\))?}} [type=__read_only image2d_array_msaa_t] [typekind=OCLImage2dArrayMSAARO] [isPOD=1]
|
|
||||||
+// CHECK: ParmDecl=scalarOCLImage2dMSAADepthRO:37:70 (Definition){{( \(invalid\))?}} [type=__read_only image2d_msaa_depth_t] [typekind=OCLImage2dMSAADepthRO] [isPOD=1]
|
|
||||||
+// CHECK: ParmDecl=scalarOCLImage2dArrayMSAADepthRO:38:81 (Definition){{( \(invalid\))?}} [type=__read_only image2d_array_msaa_depth_t] [typekind=OCLImage2dArrayMSAADepthRO] [isPOD=1]
|
|
||||||
// CHECK: ParmDecl=scalarOCLImage3dRO:39:50 (Definition) [type=__read_only image3d_t] [typekind=OCLImage3dRO] [isPOD=1]
|
|
||||||
|
|
||||||
void kernel OCLImage1dWOTest(write_only image1d_t scalarOCLImage1dWO);
|
|
||||||
@@ -71,11 +71,11 @@ void kernel OCLImage3dWOTest(write_only image3d_t scalarOCLImage3dWO);
|
|
||||||
// CHECK: ParmDecl=scalarOCLImage2dArrayWO:58:62 (Definition) [type=__write_only image2d_array_t] [typekind=OCLImage2dArrayWO] [isPOD=1]
|
|
||||||
// CHECK: ParmDecl=scalarOCLImage2dDepthWO:59:62 (Definition) [type=__write_only image2d_depth_t] [typekind=OCLImage2dDepthWO] [isPOD=1]
|
|
||||||
// CHECK: ParmDecl=scalarOCLImage2dArrayDepthWO:60:73 (Definition) [type=__write_only image2d_array_depth_t] [typekind=OCLImage2dArrayDepthWO] [isPOD=1]
|
|
||||||
-// CHECK: ParmDecl=scalarOCLImage2dMSAAWO:61:60 (Definition) [type=__write_only image2d_msaa_t] [typekind=OCLImage2dMSAAWO] [isPOD=1]
|
|
||||||
-// CHECK: ParmDecl=scalarOCLImage2dArrayMSAAWO:62:71 (Definition) [type=__write_only image2d_array_msaa_t] [typekind=OCLImage2dArrayMSAAWO] [isPOD=1]
|
|
||||||
-// CHECK: ParmDecl=scalarOCLImage2dMSAADepthWO:63:71 (Definition) [type=__write_only image2d_msaa_depth_t] [typekind=OCLImage2dMSAADepthWO] [isPOD=1]
|
|
||||||
-// CHECK: ParmDecl=scalarOCLImage2dArrayMSAADepthWO:64:82 (Definition) [type=__write_only image2d_array_msaa_depth_t] [typekind=OCLImage2dArrayMSAADepthWO] [isPOD=1]
|
|
||||||
-// CHECK: ParmDecl=scalarOCLImage3dWO:65:51 (Definition) [type=__write_only image3d_t] [typekind=OCLImage3dWO] [isPOD=1]
|
|
||||||
+// CHECK: ParmDecl=scalarOCLImage2dMSAAWO:61:60 (Definition){{( \(invalid\))?}} [type=__write_only image2d_msaa_t] [typekind=OCLImage2dMSAAWO] [isPOD=1]
|
|
||||||
+// CHECK: ParmDecl=scalarOCLImage2dArrayMSAAWO:62:71 (Definition){{( \(invalid\))?}} [type=__write_only image2d_array_msaa_t] [typekind=OCLImage2dArrayMSAAWO] [isPOD=1]
|
|
||||||
+// CHECK: ParmDecl=scalarOCLImage2dMSAADepthWO:63:71 (Definition){{( \(invalid\))?}} [type=__write_only image2d_msaa_depth_t] [typekind=OCLImage2dMSAADepthWO] [isPOD=1]
|
|
||||||
+// CHECK: ParmDecl=scalarOCLImage2dArrayMSAADepthWO:64:82 (Definition){{( \(invalid\))?}} [type=__write_only image2d_array_msaa_depth_t] [typekind=OCLImage2dArrayMSAADepthWO] [isPOD=1]
|
|
||||||
+// CHECK: ParmDecl=scalarOCLImage3dWO:65:51 (Definition){{( \(invalid\))?}} [type=__write_only image3d_t] [typekind=OCLImage3dWO] [isPOD=1]
|
|
||||||
|
|
||||||
void kernel OCLImage1dRWTest(read_write image1d_t scalarOCLImage1dRW);
|
|
||||||
void kernel OCLImage1dArrayRWTest(read_write image1d_array_t scalarOCLImage1dArrayRW);
|
|
||||||
@@ -97,10 +97,10 @@ void kernel OCLImage3dRWTest(read_write image3d_t scalarOCLImage3dRW);
|
|
||||||
// CHECK: ParmDecl=scalarOCLImage2dArrayRW:84:62 (Definition) [type=__read_write image2d_array_t] [typekind=OCLImage2dArrayRW] [isPOD=1]
|
|
||||||
// CHECK: ParmDecl=scalarOCLImage2dDepthRW:85:62 (Definition) [type=__read_write image2d_depth_t] [typekind=OCLImage2dDepthRW] [isPOD=1]
|
|
||||||
// CHECK: ParmDecl=scalarOCLImage2dArrayDepthRW:86:73 (Definition) [type=__read_write image2d_array_depth_t] [typekind=OCLImage2dArrayDepthRW] [isPOD=1]
|
|
||||||
-// CHECK: ParmDecl=scalarOCLImage2dMSAARW:87:60 (Definition) [type=__read_write image2d_msaa_t] [typekind=OCLImage2dMSAARW] [isPOD=1]
|
|
||||||
-// CHECK: ParmDecl=scalarOCLImage2dArrayMSAARW:88:71 (Definition) [type=__read_write image2d_array_msaa_t] [typekind=OCLImage2dArrayMSAARW] [isPOD=1]
|
|
||||||
-// CHECK: ParmDecl=scalarOCLImage2dMSAADepthRW:89:71 (Definition) [type=__read_write image2d_msaa_depth_t] [typekind=OCLImage2dMSAADepthRW] [isPOD=1]
|
|
||||||
-// CHECK: ParmDecl=scalarOCLImage2dArrayMSAADepthRW:90:82 (Definition) [type=__read_write image2d_array_msaa_depth_t] [typekind=OCLImage2dArrayMSAADepthRW] [isPOD=1]
|
|
||||||
+// CHECK: ParmDecl=scalarOCLImage2dMSAARW:87:60 (Definition){{( \(invalid\))?}} [type=__read_write image2d_msaa_t] [typekind=OCLImage2dMSAARW] [isPOD=1]
|
|
||||||
+// CHECK: ParmDecl=scalarOCLImage2dArrayMSAARW:88:71 (Definition){{( \(invalid\))?}} [type=__read_write image2d_array_msaa_t] [typekind=OCLImage2dArrayMSAARW] [isPOD=1]
|
|
||||||
+// CHECK: ParmDecl=scalarOCLImage2dMSAADepthRW:89:71 (Definition){{( \(invalid\))?}} [type=__read_write image2d_msaa_depth_t] [typekind=OCLImage2dMSAADepthRW] [isPOD=1]
|
|
||||||
+// CHECK: ParmDecl=scalarOCLImage2dArrayMSAADepthRW:90:82 (Definition){{( \(invalid\))?}} [type=__read_write image2d_array_msaa_depth_t] [typekind=OCLImage2dArrayMSAADepthRW] [isPOD=1]
|
|
||||||
// CHECK: ParmDecl=scalarOCLImage3dRW:91:51 (Definition) [type=__read_write image3d_t] [typekind=OCLImage3dRW] [isPOD=1]
|
|
||||||
|
|
||||||
void kernel intPipeTestRO(read_only pipe int scalarPipe);
|
|
||||||
diff --git a/test/Index/print-type-size.cpp b/test/Index/print-type-size.cpp
|
|
||||||
index 45de93f308..1ea5346273 100644
|
|
||||||
--- a/tools/clang/test/Index/print-type-size.cpp
|
|
||||||
+++ b/tools/clang/test/Index/print-type-size.cpp
|
|
||||||
@@ -4,8 +4,8 @@
|
|
||||||
|
|
||||||
namespace basic {
|
|
||||||
|
|
||||||
-// CHECK64: VarDecl=v:[[@LINE+2]]:6 (Definition) [type=void] [typekind=Void]
|
|
||||||
-// CHECK32: VarDecl=v:[[@LINE+1]]:6 (Definition) [type=void] [typekind=Void]
|
|
||||||
+// CHECK64: VarDecl=v:[[@LINE+2]]:6 (Definition) (invalid) [type=void] [typekind=Void]
|
|
||||||
+// CHECK32: VarDecl=v:[[@LINE+1]]:6 (Definition) (invalid) [type=void] [typekind=Void]
|
|
||||||
void v;
|
|
||||||
|
|
||||||
// CHECK64: VarDecl=v1:[[@LINE+2]]:7 (Definition) [type=void *] [typekind=Pointer] [sizeof=8] [alignof=8]
|
|
||||||
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
|
|
||||||
index cf3581e259..759ed449a4 100644
|
|
||||||
--- a/tools/clang/tools/c-index-test/c-index-test.c
|
|
||||||
+++ b/tools/clang/tools/c-index-test/c-index-test.c
|
|
||||||
@@ -810,6 +810,8 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
|
|
||||||
printf(" (variadic)");
|
|
||||||
if (clang_Cursor_isObjCOptional(Cursor))
|
|
||||||
printf(" (@optional)");
|
|
||||||
+ if (clang_isInvalidDeclaration(Cursor))
|
|
||||||
+ printf(" (invalid)");
|
|
||||||
|
|
||||||
switch (clang_getCursorExceptionSpecificationType(Cursor))
|
|
||||||
{
|
|
||||||
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
|
|
||||||
index 9ba4d5bf30..584de42e7c 100644
|
|
||||||
--- a/tools/clang/tools/libclang/CIndex.cpp
|
|
||||||
+++ b/tools/clang/tools/libclang/CIndex.cpp
|
|
||||||
@@ -5346,6 +5346,15 @@ unsigned clang_isDeclaration(enum CXCursorKind K) {
|
|
||||||
(K >= CXCursor_FirstExtraDecl && K <= CXCursor_LastExtraDecl);
|
|
||||||
}
|
|
||||||
|
|
||||||
+unsigned clang_isInvalidDeclaration(CXCursor C) {
|
|
||||||
+ if (clang_isDeclaration(C.kind)) {
|
|
||||||
+ if (const Decl *D = getCursorDecl(C))
|
|
||||||
+ return D->isInvalidDecl();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
unsigned clang_isReference(enum CXCursorKind K) {
|
|
||||||
return K >= CXCursor_FirstRef && K <= CXCursor_LastRef;
|
|
||||||
}
|
|
||||||
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
|
|
||||||
index e0d178a529..7192baab6a 100644
|
|
||||||
--- a/tools/clang/tools/libclang/libclang.exports
|
|
||||||
+++ b/tools/clang/tools/libclang/libclang.exports
|
|
||||||
@@ -286,6 +286,7 @@ clang_isAttribute
|
|
||||||
clang_isConstQualifiedType
|
|
||||||
clang_isCursorDefinition
|
|
||||||
clang_isDeclaration
|
|
||||||
+clang_isInvalidDeclaration
|
|
||||||
clang_isExpression
|
|
||||||
clang_isFileMultipleIncludeGuarded
|
|
||||||
clang_isFunctionTypeVariadic
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
--- a/tools/clang/test/Index/annotate-tokens.cpp
|
|
||||||
+++ b/tools/clang/test/Index/annotate-tokens.cpp
|
|
||||||
@@ -37,7 +37,9 @@ class C {
|
|
||||||
~C();
|
|
||||||
};
|
|
||||||
|
|
||||||
-// RUN: c-index-test -test-annotate-tokens=%s:1:1:38:1 %s -fno-delayed-template-parsing | FileCheck %s
|
|
||||||
+auto test5(X) -> X;
|
|
||||||
+
|
|
||||||
+// RUN: c-index-test -test-annotate-tokens=%s:1:1:41:1 %s -std=c++14 -fno-delayed-template-parsing | FileCheck %s
|
|
||||||
// CHECK: Keyword: "struct" [1:1 - 1:7] StructDecl=bonk:1:8 (Definition)
|
|
||||||
// CHECK: Identifier: "bonk" [1:8 - 1:12] StructDecl=bonk:1:8 (Definition)
|
|
||||||
// CHECK: Punctuation: "{" [1:13 - 1:14] StructDecl=bonk:1:8 (Definition)
|
|
||||||
@@ -184,6 +186,14 @@ class C {
|
|
||||||
// CHECK: Punctuation: "}" [29:22 - 29:23] CompoundStmt=
|
|
||||||
// CHECK: Punctuation: "~" [37:3 - 37:4] CXXDestructor=~C:37:3
|
|
||||||
// CHECK: Identifier: "C" [37:4 - 37:5] CXXDestructor=~C:37:3
|
|
||||||
+// CHECK: Keyword: "auto" [40:1 - 40:5] FunctionDecl=test5:40:6
|
|
||||||
+// CHECK: Identifier: "test5" [40:6 - 40:11] FunctionDecl=test5:40:6
|
|
||||||
+// CHECK: Punctuation: "(" [40:11 - 40:12] FunctionDecl=test5:40:6
|
|
||||||
+// CHECK: Identifier: "X" [40:12 - 40:13] TypeRef=struct X:7:8
|
|
||||||
+// CHECK: Punctuation: ")" [40:13 - 40:14] FunctionDecl=test5:40:6
|
|
||||||
+// CHECK: Punctuation: "->" [40:15 - 40:17] FunctionDecl=test5:40:6
|
|
||||||
+// CHECK: Identifier: "X" [40:18 - 40:19] TypeRef=struct X:7:8
|
|
||||||
+// CHECK: Punctuation: ";" [40:19 - 40:20]
|
|
||||||
|
|
||||||
// RUN: env LIBCLANG_DISABLE_CRASH_RECOVERY=1 c-index-test -test-annotate-tokens=%s:32:1:32:13 %s | FileCheck %s -check-prefix=CHECK2
|
|
||||||
// CHECK2: Keyword: "if" [32:3 - 32:5] IfStmt=
|
|
||||||
--- a/tools/clang/tools/libclang/CIndex.cpp
|
|
||||||
+++ b/tools/clang/tools/libclang/CIndex.cpp
|
|
||||||
@@ -783,6 +783,16 @@ bool CursorVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static bool HasTrailingReturnType(FunctionDecl *ND) {
|
|
||||||
+ const QualType Ty = ND->getType();
|
|
||||||
+ if (const FunctionType *AFT = Ty->getAs<FunctionType>()) {
|
|
||||||
+ if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(AFT))
|
|
||||||
+ return FT->hasTrailingReturn();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return false;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/// \brief Compare two base or member initializers based on their source order.
|
|
||||||
static int CompareCXXCtorInitializers(CXXCtorInitializer *const *X,
|
|
||||||
CXXCtorInitializer *const *Y) {
|
|
||||||
@@ -802,14 +812,16 @@ bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
|
|
||||||
// written. This requires a bit of work.
|
|
||||||
TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
|
|
||||||
FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>();
|
|
||||||
+ const bool HasTrailingRT = HasTrailingReturnType(ND);
|
|
||||||
|
|
||||||
// If we have a function declared directly (without the use of a typedef),
|
|
||||||
// visit just the return type. Otherwise, just visit the function's type
|
|
||||||
// now.
|
|
||||||
- if ((FTL && !isa<CXXConversionDecl>(ND) && Visit(FTL.getReturnLoc())) ||
|
|
||||||
+ if ((FTL && !isa<CXXConversionDecl>(ND) && !HasTrailingRT &&
|
|
||||||
+ Visit(FTL.getReturnLoc())) ||
|
|
||||||
(!FTL && Visit(TL)))
|
|
||||||
return true;
|
|
||||||
-
|
|
||||||
+
|
|
||||||
// Visit the nested-name-specifier, if present.
|
|
||||||
if (NestedNameSpecifierLoc QualifierLoc = ND->getQualifierLoc())
|
|
||||||
if (VisitNestedNameSpecifierLoc(QualifierLoc))
|
|
||||||
@@ -825,7 +837,11 @@ bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
|
|
||||||
// Visit the function parameters, if we have a function type.
|
|
||||||
if (FTL && VisitFunctionTypeLoc(FTL, true))
|
|
||||||
return true;
|
|
||||||
-
|
|
||||||
+
|
|
||||||
+ // Visit the function's trailing return type.
|
|
||||||
+ if (FTL && HasTrailingRT && Visit(FTL.getReturnLoc()))
|
|
||||||
+ return true;
|
|
||||||
+
|
|
||||||
// FIXME: Attributes?
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
|
|
||||||
index f2397d1b63..0f4ade266c 100644
|
|
||||||
--- a/tools/clang/include/clang-c/Index.h
|
|
||||||
+++ b/tools/clang/include/clang-c/Index.h
|
|
||||||
@@ -34,6 +34,7 @@
|
|
||||||
#define CINDEX_VERSION_MAJOR 0
|
|
||||||
#define CINDEX_VERSION_MINOR 43
|
|
||||||
#define CINDEX_VERSION_HAS_ISINVALIDECL_BACKPORTED
|
|
||||||
+#define CINDEX_VERSION_HAS_GETFILECONTENTS_BACKPORTED
|
|
||||||
|
|
||||||
#define CINDEX_VERSION_ENCODE(major, minor) ( \
|
|
||||||
((major) * 10000) \
|
|
||||||
@@ -394,6 +395,21 @@ clang_isFileMultipleIncludeGuarded(CXTranslationUnit tu, CXFile file);
|
|
||||||
CINDEX_LINKAGE CXFile clang_getFile(CXTranslationUnit tu,
|
|
||||||
const char *file_name);
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * \brief Retrieve the buffer associated with the given file.
|
|
||||||
+ *
|
|
||||||
+ * \param tu the translation unit
|
|
||||||
+ *
|
|
||||||
+ * \param file the file for which to retrieve the buffer.
|
|
||||||
+ *
|
|
||||||
+ * \param size [out] if non-NULL, will be set to the size of the buffer.
|
|
||||||
+ *
|
|
||||||
+ * \returns a pointer to the buffer in memory that holds the contents of
|
|
||||||
+ * \p file, or a NULL pointer when the file is not loaded.
|
|
||||||
+ */
|
|
||||||
+CINDEX_LINKAGE const char *clang_getFileContents(CXTranslationUnit tu,
|
|
||||||
+ CXFile file, size_t *size);
|
|
||||||
+
|
|
||||||
/**
|
|
||||||
* \brief Returns non-zero if the \c file1 and \c file2 point to the same file,
|
|
||||||
* or they are both NULL.
|
|
||||||
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
|
|
||||||
index 13599e1910..7902e8a030 100644
|
|
||||||
--- a/tools/clang/tools/libclang/CIndex.cpp
|
|
||||||
+++ b/tools/clang/tools/libclang/CIndex.cpp
|
|
||||||
@@ -4148,6 +4148,27 @@ CXFile clang_getFile(CXTranslationUnit TU, const char *file_name) {
|
|
||||||
return const_cast<FileEntry *>(FMgr.getFile(file_name));
|
|
||||||
}
|
|
||||||
|
|
||||||
+const char *clang_getFileContents(CXTranslationUnit TU, CXFile file,
|
|
||||||
+ size_t *size) {
|
|
||||||
+ if (isNotUsableTU(TU)) {
|
|
||||||
+ LOG_BAD_TU(TU);
|
|
||||||
+ return nullptr;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ const SourceManager &SM = cxtu::getASTUnit(TU)->getSourceManager();
|
|
||||||
+ FileID fid = SM.translateFile(static_cast<FileEntry *>(file));
|
|
||||||
+ bool Invalid = true;
|
|
||||||
+ llvm::MemoryBuffer *buf = SM.getBuffer(fid, &Invalid);
|
|
||||||
+ if (Invalid) {
|
|
||||||
+ if (size)
|
|
||||||
+ *size = 0;
|
|
||||||
+ return nullptr;
|
|
||||||
+ }
|
|
||||||
+ if (size)
|
|
||||||
+ *size = buf->getBufferSize();
|
|
||||||
+ return buf->getBufferStart();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
unsigned clang_isFileMultipleIncludeGuarded(CXTranslationUnit TU,
|
|
||||||
CXFile file) {
|
|
||||||
if (isNotUsableTU(TU)) {
|
|
||||||
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
|
|
||||||
index 7192baab6a..c788abb881 100644
|
|
||||||
--- a/tools/clang/tools/libclang/libclang.exports
|
|
||||||
+++ b/tools/clang/tools/libclang/libclang.exports
|
|
||||||
@@ -216,6 +216,7 @@ clang_getExceptionSpecificationType
|
|
||||||
clang_getFieldDeclBitWidth
|
|
||||||
clang_getExpansionLocation
|
|
||||||
clang_getFile
|
|
||||||
+clang_getFileContents
|
|
||||||
clang_getFileLocation
|
|
||||||
clang_getFileName
|
|
||||||
clang_getFileTime
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
--- a/tools/clang/lib/Serialization/ASTReader.cpp
|
|
||||||
+++ b/tools/clang/lib/Serialization/ASTReader.cpp
|
|
||||||
@@ -1220,6 +1220,7 @@
|
|
||||||
|
|
||||||
// Parse the file names
|
|
||||||
std::map<int, int> FileIDs;
|
|
||||||
+ FileIDs[-1] = -1; // For unspecified filenames.
|
|
||||||
for (unsigned I = 0; Record[Idx]; ++I) {
|
|
||||||
// Extract the file name
|
|
||||||
auto Filename = ReadPath(F, Record, Idx);
|
|
||||||
--- a/tools/clang/lib/Serialization/ASTWriter.cpp
|
|
||||||
+++ b/tools/clang/lib/Serialization/ASTWriter.cpp
|
|
||||||
@@ -2363,12 +2363,13 @@
|
|
||||||
|
|
||||||
// Emit the needed file names.
|
|
||||||
llvm::DenseMap<int, int> FilenameMap;
|
|
||||||
+ FilenameMap[-1] = -1; // For unspecified filenames.
|
|
||||||
for (const auto &L : LineTable) {
|
|
||||||
if (L.first.ID < 0)
|
|
||||||
continue;
|
|
||||||
for (auto &LE : L.second) {
|
|
||||||
if (FilenameMap.insert(std::make_pair(LE.FilenameID,
|
|
||||||
- FilenameMap.size())).second)
|
|
||||||
+ FilenameMap.size() - 1)).second)
|
|
||||||
AddPath(LineTable.getFilename(LE.FilenameID), Record);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
--- a/tools/clang/test/PCH/line-directive-nofilename.h
|
|
||||||
+++ b/tools/clang/test/PCH/line-directive-nofilename.h
|
|
||||||
@@ -0,0 +1,5 @@
|
|
||||||
+#line 42
|
|
||||||
+int foo; // This should appear as at line-directive-nofilename.h:42
|
|
||||||
+
|
|
||||||
+#line 100 "foobar.h"
|
|
||||||
+int bar; // This should appear as at foobar.h:100
|
|
||||||
--- a/tools/clang/test/PCH/line-directive-nofilename.c
|
|
||||||
+++ b/tools/clang/test/PCH/line-directive-nofilename.c
|
|
||||||
@@ -0,0 +1,9 @@
|
|
||||||
+// RUN: %clang_cc1 -emit-pch -o %t %S/line-directive-nofilename.h
|
|
||||||
+// RUN: not %clang_cc1 -include-pch %t -fsyntax-only %s 2>&1 | FileCheck %s
|
|
||||||
+
|
|
||||||
+// This causes an "error: redefinition" diagnostic. The notes will have the
|
|
||||||
+// locations of the declarations from the PCH file.
|
|
||||||
+double foo, bar;
|
|
||||||
+
|
|
||||||
+// CHECK: line-directive-nofilename.h:42:5: note: previous definition is here
|
|
||||||
+// CHECK: foobar.h:100:5: note: previous definition is here
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
--- a/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
|
|
||||||
+++ b/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
|
|
||||||
@@ -22,6 +22,7 @@
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "ClangSACheckers.h"
|
|
||||||
+#include "clang/AST/ParentMap.h"
|
|
||||||
#include "clang/AST/RecursiveASTVisitor.h"
|
|
||||||
#include "clang/Basic/Builtins.h"
|
|
||||||
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
|
|
||||||
@@ -262,8 +263,19 @@
|
|
||||||
if (const MemRegion *Target = Ctor->getCXXThisVal().getAsRegion()) {
|
|
||||||
// We just finished a base constructor. Now we can use the subclass's
|
|
||||||
// type when resolving virtual calls.
|
|
||||||
- const Decl *D = C.getLocationContext()->getDecl();
|
|
||||||
- recordFixedType(Target, cast<CXXConstructorDecl>(D), C);
|
|
||||||
+ const LocationContext *LCtx = C.getLocationContext();
|
|
||||||
+
|
|
||||||
+ // FIXME: In C++17 classes with non-virtual bases may be treated as
|
|
||||||
+ // aggregates, and in such case no top-frame constructor will be called.
|
|
||||||
+ // Figure out if we need to do anything in this case.
|
|
||||||
+ // FIXME: Instead of relying on the ParentMap, we should have the
|
|
||||||
+ // trigger-statement (InitListExpr in this case) available in this
|
|
||||||
+ // callback, ideally as part of CallEvent.
|
|
||||||
+ if (dyn_cast_or_null<InitListExpr>(
|
|
||||||
+ LCtx->getParentMap().getParent(Ctor->getOriginExpr())))
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ recordFixedType(Target, cast<CXXConstructorDecl>(LCtx->getDecl()), C);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
--- a/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
|
|
||||||
+++ b/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
|
|
||||||
@@ -14,6 +14,7 @@
|
|
||||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
|
|
||||||
#include "clang/AST/DeclCXX.h"
|
|
||||||
#include "clang/AST/StmtCXX.h"
|
|
||||||
+#include "clang/AST/ParentMap.h"
|
|
||||||
#include "clang/Basic/PrettyStackTrace.h"
|
|
||||||
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
|
|
||||||
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
|
|
||||||
@@ -267,6 +268,23 @@
|
|
||||||
}
|
|
||||||
// FALLTHROUGH
|
|
||||||
case CXXConstructExpr::CK_NonVirtualBase:
|
|
||||||
+ // In C++17, classes with non-virtual bases may be aggregates, so they would
|
|
||||||
+ // be initialized as aggregates without a constructor call, so we may have
|
|
||||||
+ // a base class constructed directly into an initializer list without
|
|
||||||
+ // having the derived-class constructor call on the previous stack frame.
|
|
||||||
+ // Initializer lists may be nested into more initializer lists that
|
|
||||||
+ // correspond to surrounding aggregate initializations.
|
|
||||||
+ // FIXME: For now this code essentially bails out. We need to find the
|
|
||||||
+ // correct target region and set it.
|
|
||||||
+ // FIXME: Instead of relying on the ParentMap, we should have the
|
|
||||||
+ // trigger-statement (InitListExpr in this case) passed down from CFG or
|
|
||||||
+ // otherwise always available during construction.
|
|
||||||
+ if (dyn_cast_or_null<InitListExpr>(LCtx->getParentMap().getParent(CE))) {
|
|
||||||
+ MemRegionManager &MRMgr = getSValBuilder().getRegionManager();
|
|
||||||
+ Target = MRMgr.getCXXTempObjectRegion(CE, LCtx);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ // FALLTHROUGH
|
|
||||||
case CXXConstructExpr::CK_Delegating: {
|
|
||||||
const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
|
|
||||||
Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor,
|
|
||||||
--- a/tools/clang/test/Analysis/initializer.cpp
|
|
||||||
+++ a/tools/clang/test/Analysis/initializer.cpp
|
|
||||||
@@ -1,4 +1,5 @@
|
|
||||||
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=constructors -std=c++11 -verify %s
|
|
||||||
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks,debug.ExprInspection -analyzer-config c++-inlining=constructors -std=c++17 -DCPLUSPLUS17 -verify %s
|
|
||||||
|
|
||||||
void clang_analyzer_eval(bool);
|
|
||||||
|
|
||||||
@@ -224,3 +225,42 @@
|
|
||||||
const char(&f)[2];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+namespace CXX17_aggregate_construction {
|
|
||||||
+struct A {
|
|
||||||
+ A();
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+struct B: public A {
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+struct C: public B {
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+struct D: public virtual A {
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+// In C++17, classes B and C are aggregates, so they will be constructed
|
|
||||||
+// without actually calling their trivial constructor. Used to crash.
|
|
||||||
+void foo() {
|
|
||||||
+ B b = {}; // no-crash
|
|
||||||
+ const B &bl = {}; // no-crash
|
|
||||||
+ B &&br = {}; // no-crash
|
|
||||||
+
|
|
||||||
+ C c = {}; // no-crash
|
|
||||||
+ const C &cl = {}; // no-crash
|
|
||||||
+ C &&cr = {}; // no-crash
|
|
||||||
+
|
|
||||||
+ D d = {}; // no-crash
|
|
||||||
+
|
|
||||||
+#ifdef CPLUSPLUS17
|
|
||||||
+ C cd = {{}}; // no-crash
|
|
||||||
+ const C &cdl = {{}}; // no-crash
|
|
||||||
+ C &&cdr = {{}}; // no-crash
|
|
||||||
+
|
|
||||||
+ const B &bll = {{}}; // no-crash
|
|
||||||
+ const B &bcl = C({{}}); // no-crash
|
|
||||||
+ B &&bcr = C({{}}); // no-crash
|
|
||||||
+#endif
|
|
||||||
+}
|
|
||||||
+}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
--- a/tools/clang/include/clang/Sema/ScopeInfo.h
|
|
||||||
+++ b/tools/clang/include/clang/Sema/ScopeInfo.h
|
|
||||||
@@ -560,6 +560,7 @@
|
|
||||||
void markUsed(bool IsODRUse) { (IsODRUse ? ODRUsed : NonODRUsed) = true; }
|
|
||||||
|
|
||||||
VarDecl *getVariable() const {
|
|
||||||
+ assert(isVariableCapture());
|
|
||||||
return VarAndNestedAndThis.getPointer();
|
|
||||||
}
|
|
||||||
|
|
||||||
--- a/tools/clang/lib/Sema/SemaLambda.cpp
|
|
||||||
+++ b/tools/clang/lib/Sema/SemaLambda.cpp
|
|
||||||
@@ -1481,6 +1481,9 @@
|
|
||||||
if (CaptureHasSideEffects(From))
|
|
||||||
return;
|
|
||||||
|
|
||||||
+ if (From.isVLATypeCapture())
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
auto diag = Diag(From.getLocation(), diag::warn_unused_lambda_capture);
|
|
||||||
if (From.isThisCapture())
|
|
||||||
diag << "'this'";
|
|
||||||
--- a/tools/clang/test/SemaCXX/warn-unused-lambda-capture.cpp
|
|
||||||
+++ b/tools/clang/test/SemaCXX/warn-unused-lambda-capture.cpp
|
|
||||||
@@ -191,3 +191,12 @@
|
|
||||||
void test_use_template() {
|
|
||||||
test_templated<int>(); // expected-note{{in instantiation of function template specialization 'test_templated<int>' requested here}}
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+namespace pr35555 {
|
|
||||||
+int a;
|
|
||||||
+void b() {
|
|
||||||
+ int c[a];
|
|
||||||
+ auto vla_used = [&c] { return c[0]; };
|
|
||||||
+ auto vla_unused = [&c] {}; // expected-warning{{lambda capture 'c' is not used}}
|
|
||||||
+}
|
|
||||||
+} // namespace pr35555
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
--- a/tools/clang/lib/Lex/PPCaching.cpp
|
|
||||||
+++ b/tools/clang/lib/Lex/PPCaching.cpp
|
|
||||||
@@ -105,8 +105,10 @@
|
|
||||||
}
|
|
||||||
|
|
||||||
void Preprocessor::EnterCachingLexMode() {
|
|
||||||
- if (InCachingLexMode())
|
|
||||||
+ if (InCachingLexMode()) {
|
|
||||||
+ assert(CurLexerKind == CLK_CachingLexer && "Unexpected lexer kind");
|
|
||||||
return;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
PushIncludeMacroStack();
|
|
||||||
CurLexerKind = CLK_CachingLexer;
|
|
||||||
--- a/tools/clang/lib/Lex/PPLexerChange.cpp
|
|
||||||
+++ b/tools/clang/lib/Lex/PPLexerChange.cpp
|
|
||||||
@@ -444,6 +444,7 @@
|
|
||||||
}
|
|
||||||
|
|
||||||
CurPPLexer = nullptr;
|
|
||||||
+ recomputeCurLexerKind();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/tools/clang/test/CodeCompletion/Inputs/comments.h
|
|
||||||
@@ -0,0 +1,4 @@
|
|
||||||
+// PR32732
|
|
||||||
+struct B {
|
|
||||||
+ // <- code completion
|
|
||||||
+};
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/tools/clang/test/CodeCompletion/comments.cpp
|
|
||||||
@@ -0,0 +1,13 @@
|
|
||||||
+// Note: the run lines follow their respective tests, since line/column
|
|
||||||
+// matter in this test.
|
|
||||||
+
|
|
||||||
+#include "comments.h"
|
|
||||||
+
|
|
||||||
+struct A {
|
|
||||||
+ // <- code completion
|
|
||||||
+ /* <- code completion */
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+// RUN: %clang_cc1 -I %S/Inputs -fsyntax-only -code-completion-at=%s:7:6 %s
|
|
||||||
+// RUN: %clang_cc1 -I %S/Inputs -fsyntax-only -code-completion-at=%s:8:6 %s
|
|
||||||
+// RUN: %clang_cc1 -I %S/Inputs -fsyntax-only -code-completion-at=%S/Inputs/comments.h:3:6 %s
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
diff --git a/tools/clang/tools/libclang/CIndex.cpp b/tools/clang/tools/libclang/CIndex.cpp
|
|
||||||
index 66b6edc8b1..281ab77c23 100644
|
|
||||||
--- a/tools/clang/tools/libclang/CIndex.cpp
|
|
||||||
+++ b/tools/clang/tools/libclang/CIndex.cpp
|
|
||||||
@@ -8479,4 +8479,8 @@ static int LLVM_ATTRIBUTE_UNUSED ClangTidyPluginAnchorDestination =
|
|
||||||
extern volatile int ClangIncludeFixerPluginAnchorSource;
|
|
||||||
static int LLVM_ATTRIBUTE_UNUSED ClangIncludeFixerPluginAnchorDestination =
|
|
||||||
ClangIncludeFixerPluginAnchorSource;
|
|
||||||
+
|
|
||||||
+// This anchor is used to force the linker to link the clazy plugin.
|
|
||||||
+extern volatile int ClazyPluginAnchorSource;
|
|
||||||
+static int LLVM_ATTRIBUTE_UNUSED ClazyPluginAnchorDestination = ClazyPluginAnchorSource;
|
|
||||||
#endif
|
|
||||||
diff --git a/tools/clang/tools/libclang/CMakeLists.txt b/tools/clang/tools/libclang/CMakeLists.txt
|
|
||||||
index 4440637820..6798d2ee8b 100644
|
|
||||||
--- a/tools/clang/tools/libclang/CMakeLists.txt
|
|
||||||
+++ b/tools/clang/tools/libclang/CMakeLists.txt
|
|
||||||
@@ -51,6 +51,7 @@ if (TARGET clangTidyPlugin)
|
|
||||||
add_definitions(-DCLANG_TOOL_EXTRA_BUILD)
|
|
||||||
list(APPEND LIBS clangTidyPlugin)
|
|
||||||
list(APPEND LIBS clangIncludeFixerPlugin)
|
|
||||||
+ list(APPEND LIBS clazyPlugin)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
find_library(DL_LIBRARY_PATH dl)
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
diff --git a/tools/clang/tools/extra/CMakeLists.txt b/tools/clang/tools/extra/CMakeLists.txt
|
|
||||||
index 760340a6..53f720c4 100644
|
|
||||||
--- a/tools/clang/tools/extra/CMakeLists.txt
|
|
||||||
+++ b/tools/clang/tools/extra/CMakeLists.txt
|
|
||||||
@@ -5,6 +5,8 @@ if(CLANG_ENABLE_STATIC_ANALYZER)
|
|
||||||
add_subdirectory(clang-tidy)
|
|
||||||
add_subdirectory(clang-tidy-vs)
|
|
||||||
endif()
|
|
||||||
+set(CLAZY_BUILD_WITH_CLANG 1)
|
|
||||||
+add_subdirectory(clazy)
|
|
||||||
|
|
||||||
add_subdirectory(change-namespace)
|
|
||||||
add_subdirectory(clang-query)
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
diff --git a/lib/Transforms/CMakeLists.txt b/lib/Transforms/CMakeLists.txt
|
|
||||||
index 67bdeb27212..7fcddb15904 100644
|
|
||||||
--- a/lib/Transforms/CMakeLists.txt
|
|
||||||
+++ b/lib/Transforms/CMakeLists.txt
|
|
||||||
@@ -4,6 +4,5 @@ add_subdirectory(InstCombine)
|
|
||||||
add_subdirectory(Scalar)
|
|
||||||
add_subdirectory(IPO)
|
|
||||||
add_subdirectory(Vectorize)
|
|
||||||
-add_subdirectory(Hello)
|
|
||||||
add_subdirectory(ObjCARC)
|
|
||||||
add_subdirectory(Coroutines)
|
|
||||||
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
|
|
||||||
index 6cf5103bf44..0b9608a2e52 100644
|
|
||||||
--- a/test/CMakeLists.txt
|
|
||||||
+++ b/test/CMakeLists.txt
|
|
||||||
@@ -35,7 +35,6 @@ endif()
|
|
||||||
set(LLVM_TEST_DEPENDS
|
|
||||||
BugpointPasses
|
|
||||||
FileCheck
|
|
||||||
- LLVMHello
|
|
||||||
UnitTests
|
|
||||||
bugpoint
|
|
||||||
count
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
diff --git a/lib/Support/MemoryBuffer.cpp b/lib/Support/MemoryBuffer.cpp
|
|
||||||
index 85e782b2c04..95f10753d96 100644
|
|
||||||
--- a/lib/Support/MemoryBuffer.cpp
|
|
||||||
+++ b/lib/Support/MemoryBuffer.cpp
|
|
||||||
@@ -284,6 +284,11 @@ static bool shouldUseMmap(int FD,
|
|
||||||
bool RequiresNullTerminator,
|
|
||||||
int PageSize,
|
|
||||||
bool IsVolatile) {
|
|
||||||
+#ifdef _WIN32
|
|
||||||
+ // Do not use mmap on Windows in order to avoid file locking
|
|
||||||
+ return false;
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
// mmap may leave the buffer without null terminator if the file size changed
|
|
||||||
// by the time the last page is mapped in, so avoid it if the file size is
|
|
||||||
// likely to change.
|
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
From 363747b90f66f097fd45a6cd665adbaf7612188a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nikolai Kosjar <nikolai.kosjar@qt.io>
|
|
||||||
Date: Mon, 15 Jan 2018 12:51:18 +0100
|
|
||||||
Subject: [PATCH 2/3] Backport: [DeclPrinter] Allow printing fully qualified
|
|
||||||
name of function declaration
|
|
||||||
|
|
||||||
https://reviews.llvm.org/D40013
|
|
||||||
---
|
|
||||||
include/clang/AST/PrettyPrinter.h | 7 +++++-
|
|
||||||
lib/AST/DeclPrinter.cpp | 16 ++++++++----
|
|
||||||
unittests/AST/DeclPrinterTest.cpp | 51 ++++++++++++++++++++++++++++++++++++---
|
|
||||||
3 files changed, 64 insertions(+), 10 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h
|
|
||||||
index 274df220e1..edcef0ae24 100644
|
|
||||||
--- a/tools/clang/include/clang/AST/PrettyPrinter.h
|
|
||||||
+++ b/tools/clang/include/clang/AST/PrettyPrinter.h
|
|
||||||
@@ -50,7 +50,8 @@ struct PrintingPolicy {
|
|
||||||
UseVoidForZeroParams(!LO.CPlusPlus),
|
|
||||||
TerseOutput(false), PolishForDeclaration(false),
|
|
||||||
Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar),
|
|
||||||
- IncludeNewlines(true), MSVCFormatting(false) { }
|
|
||||||
+ IncludeNewlines(true), MSVCFormatting(false),
|
|
||||||
+ FullyQualifiedName(false) { }
|
|
||||||
|
|
||||||
/// \brief Adjust this printing policy for cases where it's known that
|
|
||||||
/// we're printing C++ code (for instance, if AST dumping reaches a
|
|
||||||
@@ -200,6 +201,10 @@ struct PrintingPolicy {
|
|
||||||
/// prints anonymous namespaces as `anonymous namespace' and does not insert
|
|
||||||
/// spaces after template arguments.
|
|
||||||
bool MSVCFormatting : 1;
|
|
||||||
+
|
|
||||||
+ /// When true, print the fully qualified name of function declarations.
|
|
||||||
+ /// This is the opposite of SuppressScope and thus overrules it.
|
|
||||||
+ bool FullyQualifiedName : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace clang
|
|
||||||
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
|
|
||||||
index 37f08a4985..ea37abe8f6 100644
|
|
||||||
--- a/tools/clang/lib/AST/DeclPrinter.cpp
|
|
||||||
+++ b/tools/clang/lib/AST/DeclPrinter.cpp
|
|
||||||
@@ -510,13 +510,19 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
|
|
||||||
PrintingPolicy SubPolicy(Policy);
|
|
||||||
SubPolicy.SuppressSpecifiers = false;
|
|
||||||
std::string Proto;
|
|
||||||
- if (!Policy.SuppressScope) {
|
|
||||||
- if (const NestedNameSpecifier *NS = D->getQualifier()) {
|
|
||||||
- llvm::raw_string_ostream OS(Proto);
|
|
||||||
- NS->print(OS, Policy);
|
|
||||||
+
|
|
||||||
+ if (Policy.FullyQualifiedName) {
|
|
||||||
+ Proto += D->getQualifiedNameAsString();
|
|
||||||
+ } else {
|
|
||||||
+ if (!Policy.SuppressScope) {
|
|
||||||
+ if (const NestedNameSpecifier *NS = D->getQualifier()) {
|
|
||||||
+ llvm::raw_string_ostream OS(Proto);
|
|
||||||
+ NS->print(OS, Policy);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
+ Proto += D->getNameInfo().getAsString();
|
|
||||||
}
|
|
||||||
- Proto += D->getNameInfo().getAsString();
|
|
||||||
+
|
|
||||||
if (GuideDecl)
|
|
||||||
Proto = GuideDecl->getDeducedTemplate()->getDeclName().getAsString();
|
|
||||||
if (const TemplateArgumentList *TArgs = D->getTemplateSpecializationArgs()) {
|
|
||||||
diff --git a/unittests/AST/DeclPrinterTest.cpp b/unittests/AST/DeclPrinterTest.cpp
|
|
||||||
index dc1977d876..4cf8bce20e 100644
|
|
||||||
--- a/tools/clang/unittests/AST/DeclPrinterTest.cpp
|
|
||||||
+++ b/tools/clang/unittests/AST/DeclPrinterTest.cpp
|
|
||||||
@@ -104,15 +104,17 @@ PrintedDeclMatches(StringRef Code, const std::vector<std::string> &Args,
|
|
||||||
return ::testing::AssertionSuccess();
|
|
||||||
}
|
|
||||||
|
|
||||||
-::testing::AssertionResult PrintedDeclCXX98Matches(StringRef Code,
|
|
||||||
- StringRef DeclName,
|
|
||||||
- StringRef ExpectedPrinted) {
|
|
||||||
+::testing::AssertionResult
|
|
||||||
+PrintedDeclCXX98Matches(StringRef Code, StringRef DeclName,
|
|
||||||
+ StringRef ExpectedPrinted,
|
|
||||||
+ PrintingPolicyModifier PolicyModifier = nullptr) {
|
|
||||||
std::vector<std::string> Args(1, "-std=c++98");
|
|
||||||
return PrintedDeclMatches(Code,
|
|
||||||
Args,
|
|
||||||
namedDecl(hasName(DeclName)).bind("id"),
|
|
||||||
ExpectedPrinted,
|
|
||||||
- "input.cc");
|
|
||||||
+ "input.cc",
|
|
||||||
+ PolicyModifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
::testing::AssertionResult
|
|
||||||
@@ -350,6 +352,47 @@ TEST(DeclPrinter, TestFunctionDecl1) {
|
|
||||||
"void A()"));
|
|
||||||
}
|
|
||||||
|
|
||||||
+TEST(DeclPrinter, TestFreeFunctionDecl_FullyQualifiedName) {
|
|
||||||
+ ASSERT_TRUE(PrintedDeclCXX98Matches(
|
|
||||||
+ "void A();",
|
|
||||||
+ "A",
|
|
||||||
+ "void A()",
|
|
||||||
+ [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+TEST(DeclPrinter, TestFreeFunctionDeclInNamespace_FullyQualifiedName) {
|
|
||||||
+ ASSERT_TRUE(PrintedDeclCXX98Matches(
|
|
||||||
+ "namespace X { void A(); };",
|
|
||||||
+ "A",
|
|
||||||
+ "void X::A()",
|
|
||||||
+ [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+TEST(DeclPrinter, TestMemberFunction_FullyQualifiedName) {
|
|
||||||
+ ASSERT_TRUE(PrintedDeclCXX98Matches(
|
|
||||||
+ "struct X { void A(); };",
|
|
||||||
+ "A",
|
|
||||||
+ "void X::A()",
|
|
||||||
+ [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+TEST(DeclPrinter, TestMemberFunctionInNamespace_FullyQualifiedName) {
|
|
||||||
+ ASSERT_TRUE(PrintedDeclCXX98Matches(
|
|
||||||
+ "namespace Z { struct X { void A(); }; }",
|
|
||||||
+ "A",
|
|
||||||
+ "void Z::X::A()",
|
|
||||||
+ [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+TEST(DeclPrinter, TestMemberFunctionOutside_FullyQualifiedName) {
|
|
||||||
+ ASSERT_TRUE(PrintedDeclCXX98Matches(
|
|
||||||
+ "struct X { void A(); };"
|
|
||||||
+ "void X::A() {}",
|
|
||||||
+ functionDecl(hasName("A"), isDefinition()).bind("id"),
|
|
||||||
+ "void X::A()",
|
|
||||||
+ [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
TEST(DeclPrinter, TestFunctionDecl2) {
|
|
||||||
ASSERT_TRUE(PrintedDeclCXX98Matches(
|
|
||||||
"void A() {}",
|
|
||||||
--
|
|
||||||
2.15.1
|
|
||||||
|
|
||||||
@@ -1,546 +0,0 @@
|
|||||||
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
|
|
||||||
index 0f4ade266c..f188ec9d8c 100644
|
|
||||||
--- a/tools/clang/include/clang-c/Index.h
|
|
||||||
+++ b/tools/clang/include/clang-c/Index.h
|
|
||||||
@@ -35,6 +35,7 @@
|
|
||||||
#define CINDEX_VERSION_MINOR 43
|
|
||||||
#define CINDEX_VERSION_HAS_ISINVALIDECL_BACKPORTED
|
|
||||||
#define CINDEX_VERSION_HAS_GETFILECONTENTS_BACKPORTED
|
|
||||||
+#define CINDEX_VERSION_HAS_PRETTYDECL_BACKPORTED
|
|
||||||
|
|
||||||
#define CINDEX_VERSION_ENCODE(major, minor) ( \
|
|
||||||
((major) * 10000) \
|
|
||||||
@@ -4066,6 +4067,90 @@ CINDEX_LINKAGE CXSourceRange clang_Cursor_getSpellingNameRange(CXCursor,
|
|
||||||
unsigned pieceIndex,
|
|
||||||
unsigned options);
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * \brief Opaque pointer representing a policy that controls pretty printing
|
|
||||||
+ * for \c clang_getCursorPrettyPrinted.
|
|
||||||
+ */
|
|
||||||
+typedef void *CXPrintingPolicy;
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * \brief Properties for the printing policy.
|
|
||||||
+ *
|
|
||||||
+ * See \c clang::PrintingPolicy for more information.
|
|
||||||
+ */
|
|
||||||
+enum CXPrintingPolicyProperty {
|
|
||||||
+ CXPrintingPolicy_Indentation,
|
|
||||||
+ CXPrintingPolicy_SuppressSpecifiers,
|
|
||||||
+ CXPrintingPolicy_SuppressTagKeyword,
|
|
||||||
+ CXPrintingPolicy_IncludeTagDefinition,
|
|
||||||
+ CXPrintingPolicy_SuppressScope,
|
|
||||||
+ CXPrintingPolicy_SuppressUnwrittenScope,
|
|
||||||
+ CXPrintingPolicy_SuppressInitializers,
|
|
||||||
+ CXPrintingPolicy_ConstantArraySizeAsWritten,
|
|
||||||
+ CXPrintingPolicy_AnonymousTagLocations,
|
|
||||||
+ CXPrintingPolicy_SuppressStrongLifetime,
|
|
||||||
+ CXPrintingPolicy_SuppressLifetimeQualifiers,
|
|
||||||
+ CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors,
|
|
||||||
+ CXPrintingPolicy_Bool,
|
|
||||||
+ CXPrintingPolicy_Restrict,
|
|
||||||
+ CXPrintingPolicy_Alignof,
|
|
||||||
+ CXPrintingPolicy_UnderscoreAlignof,
|
|
||||||
+ CXPrintingPolicy_UseVoidForZeroParams,
|
|
||||||
+ CXPrintingPolicy_TerseOutput,
|
|
||||||
+ CXPrintingPolicy_PolishForDeclaration,
|
|
||||||
+ CXPrintingPolicy_Half,
|
|
||||||
+ CXPrintingPolicy_MSWChar,
|
|
||||||
+ CXPrintingPolicy_IncludeNewlines,
|
|
||||||
+ CXPrintingPolicy_MSVCFormatting,
|
|
||||||
+ CXPrintingPolicy_ConstantsAsWritten, /* Ops, not yet there in clang 5.0 and we do not need it. */
|
|
||||||
+ CXPrintingPolicy_SuppressImplicitBase, /* Ops, not yet there in clang 5.0 and we do not need it. */
|
|
||||||
+ CXPrintingPolicy_FullyQualifiedName,
|
|
||||||
+
|
|
||||||
+ CXPrintingPolicy_LastProperty = CXPrintingPolicy_FullyQualifiedName
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * \brief Get a property value for the given printing policy.
|
|
||||||
+ */
|
|
||||||
+CINDEX_LINKAGE unsigned
|
|
||||||
+clang_PrintingPolicy_getProperty(CXPrintingPolicy Policy,
|
|
||||||
+ enum CXPrintingPolicyProperty Property);
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * \brief Set a property value for the given printing policy.
|
|
||||||
+ */
|
|
||||||
+CINDEX_LINKAGE void
|
|
||||||
+clang_PrintingPolicy_setProperty(CXPrintingPolicy Policy,
|
|
||||||
+ enum CXPrintingPolicyProperty Property,
|
|
||||||
+ unsigned Value);
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * \brief Retrieve the default policy for the cursor.
|
|
||||||
+ *
|
|
||||||
+ * The policy should be released after use with \c
|
|
||||||
+ * clang_PrintingPolicy_dispose.
|
|
||||||
+ */
|
|
||||||
+CINDEX_LINKAGE CXPrintingPolicy clang_getCursorPrintingPolicy(CXCursor);
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * \brief Release a printing policy.
|
|
||||||
+ */
|
|
||||||
+CINDEX_LINKAGE void clang_PrintingPolicy_dispose(CXPrintingPolicy Policy);
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * \brief Pretty print declarations.
|
|
||||||
+ *
|
|
||||||
+ * \param Cursor The cursor representing a declaration.
|
|
||||||
+ *
|
|
||||||
+ * \param Policy The policy to control the entities being printed. If
|
|
||||||
+ * NULL, a default policy is used.
|
|
||||||
+ *
|
|
||||||
+ * \returns The pretty printed declaration or the empty string for
|
|
||||||
+ * other cursors.
|
|
||||||
+ */
|
|
||||||
+CINDEX_LINKAGE CXString clang_getCursorPrettyPrinted(CXCursor Cursor,
|
|
||||||
+ CXPrintingPolicy Policy);
|
|
||||||
+
|
|
||||||
/**
|
|
||||||
* \brief Retrieve the display name for the entity referenced by this cursor.
|
|
||||||
*
|
|
||||||
diff --git a/test/Index/print-display-names.cpp b/test/Index/print-display-names.cpp
|
|
||||||
index 94fe4665e6..5ba10e43bc 100644
|
|
||||||
--- a/tools/clang/test/Index/print-display-names.cpp
|
|
||||||
+++ b/tools/clang/test/Index/print-display-names.cpp
|
|
||||||
@@ -12,9 +12,20 @@ void g(ClassTmpl<T, T>);
|
|
||||||
|
|
||||||
template<> void g<int>(ClassTmpl<int, int>);
|
|
||||||
|
|
||||||
-// RUN: c-index-test -test-load-source all-display %s | FileCheck %s
|
|
||||||
-// CHECK: print-display-names.cpp:2:7: ClassTemplate=ClassTmpl<T, typename>:2:7
|
|
||||||
-// CHECK: print-display-names.cpp:6:16: ClassDecl=ClassTmpl<Integer, Integer>:6:16 (Definition)
|
|
||||||
-// CHECK: print-display-names.cpp:8:6: FunctionDecl=f(ClassTmpl<float, Integer>):8:6
|
|
||||||
-// CHECK: print-display-names.cpp:11:6: FunctionTemplate=g(ClassTmpl<T, T>):11:6
|
|
||||||
-// CHECK: print-display-names.cpp:13:17: FunctionDecl=g<>(ClassTmpl<int, int>):13:17 [Specialization of g:11:6]
|
|
||||||
+// RUN: c-index-test -test-load-source all-display %s | FileCheck %s --check-prefix=DISPLAY_NAME
|
|
||||||
+// DISPLAY_NAME: print-display-names.cpp:2:7: ClassTemplate=ClassTmpl<T, typename>:2:7
|
|
||||||
+// DISPLAY_NAME: print-display-names.cpp:6:16: ClassDecl=ClassTmpl<Integer, Integer>:6:16 (Definition)
|
|
||||||
+// DISPLAY_NAME: print-display-names.cpp:8:6: FunctionDecl=f(ClassTmpl<float, Integer>):8:6
|
|
||||||
+// DISPLAY_NAME: print-display-names.cpp:11:6: FunctionTemplate=g(ClassTmpl<T, T>):11:6
|
|
||||||
+// DISPLAY_NAME: print-display-names.cpp:13:17: FunctionDecl=g<>(ClassTmpl<int, int>):13:17 [Specialization of g:11:6]
|
|
||||||
+
|
|
||||||
+// RUN: env CINDEXTEST_PRINTINGPOLICY_TERSEOUTPUT=1 c-index-test -test-load-source all-pretty %s | FileCheck %s --check-prefix=PRETTY
|
|
||||||
+// PRETTY: print-display-names.cpp:2:7: ClassTemplate=template <typename T, typename > class ClassTmpl {}:2:7 (Definition) Extent=[1:1 - 2:20]
|
|
||||||
+// PRETTY: print-display-names.cpp:4:13: TypedefDecl=typedef int Integer:4:13 (Definition) Extent=[4:1 - 4:20]
|
|
||||||
+// PRETTY: print-display-names.cpp:6:16: ClassDecl=template<> class ClassTmpl<int, int> {}:6:16 (Definition) [Specialization of ClassTmpl:2:7] Extent=[6:1 - 6:43]
|
|
||||||
+// PRETTY: print-display-names.cpp:8:6: FunctionDecl=void f(ClassTmpl<float, Integer> p):8:6 Extent=[8:1 - 8:36]
|
|
||||||
+// PRETTY: print-display-names.cpp:8:34: ParmDecl=ClassTmpl<float, Integer> p:8:34 (Definition) Extent=[8:8 - 8:35]
|
|
||||||
+// PRETTY: print-display-names.cpp:11:6: FunctionTemplate=template <typename T> void g(ClassTmpl<T, T>):11:6 Extent=[10:1 - 11:24]
|
|
||||||
+// PRETTY: print-display-names.cpp:11:23: ParmDecl=ClassTmpl<T, T>:11:23 (Definition) Extent=[11:8 - 11:23]
|
|
||||||
+// PRETTY: print-display-names.cpp:13:17: FunctionDecl=template<> void g<int>(ClassTmpl<int, int>):13:17 [Specialization of g:11:6] [Template arg 0: kind: 1, type: int] Extent=[13:1 - 13:44]
|
|
||||||
+// PRETTY: print-display-names.cpp:13:43: ParmDecl=ClassTmpl<int, int>:13:43 (Definition) Extent=[13:24 - 13:43]
|
|
||||||
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
|
|
||||||
index 759ed449a4..ce2f549234 100644
|
|
||||||
--- a/tools/clang/tools/c-index-test/c-index-test.c
|
|
||||||
+++ b/tools/clang/tools/c-index-test/c-index-test.c
|
|
||||||
@@ -86,6 +86,69 @@ static unsigned getDefaultParsingOptions() {
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void ModifyPrintingPolicyAccordingToEnv(CXPrintingPolicy Policy) {
|
|
||||||
+ struct Mapping {
|
|
||||||
+ const char *name;
|
|
||||||
+ enum CXPrintingPolicyProperty property;
|
|
||||||
+ };
|
|
||||||
+ struct Mapping mappings[] = {
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_INDENTATION", CXPrintingPolicy_Indentation},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSPECIFIERS",
|
|
||||||
+ CXPrintingPolicy_SuppressSpecifiers},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSTAGKEYWORD",
|
|
||||||
+ CXPrintingPolicy_SuppressTagKeyword},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_INCLUDETAGDEFINITION",
|
|
||||||
+ CXPrintingPolicy_IncludeTagDefinition},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSCOPE",
|
|
||||||
+ CXPrintingPolicy_SuppressScope},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSUNWRITTENSCOPE",
|
|
||||||
+ CXPrintingPolicy_SuppressUnwrittenScope},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSINITIALIZERS",
|
|
||||||
+ CXPrintingPolicy_SuppressInitializers},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_CONSTANTARRAYSIZEASWRITTEN",
|
|
||||||
+ CXPrintingPolicy_ConstantArraySizeAsWritten},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_ANONYMOUSTAGLOCATIONS",
|
|
||||||
+ CXPrintingPolicy_AnonymousTagLocations},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSTRONGLIFETIME",
|
|
||||||
+ CXPrintingPolicy_SuppressStrongLifetime},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSLIFETIMEQUALIFIERS",
|
|
||||||
+ CXPrintingPolicy_SuppressLifetimeQualifiers},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSTEMPLATEARGSINCXXCONSTRUCTORS",
|
|
||||||
+ CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_BOOL", CXPrintingPolicy_Bool},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_RESTRICT", CXPrintingPolicy_Restrict},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_ALIGNOF", CXPrintingPolicy_Alignof},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_UNDERSCOREALIGNOF",
|
|
||||||
+ CXPrintingPolicy_UnderscoreAlignof},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_USEVOIDFORZEROPARAMS",
|
|
||||||
+ CXPrintingPolicy_UseVoidForZeroParams},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_TERSEOUTPUT", CXPrintingPolicy_TerseOutput},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_POLISHFORDECLARATION",
|
|
||||||
+ CXPrintingPolicy_PolishForDeclaration},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_HALF", CXPrintingPolicy_Half},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_MSWCHAR", CXPrintingPolicy_MSWChar},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_INCLUDENEWLINES",
|
|
||||||
+ CXPrintingPolicy_IncludeNewlines},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_MSVCFORMATTING",
|
|
||||||
+ CXPrintingPolicy_MSVCFormatting},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_CONSTANTSASWRITTEN",
|
|
||||||
+ CXPrintingPolicy_ConstantsAsWritten},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSIMPLICITBASE",
|
|
||||||
+ CXPrintingPolicy_SuppressImplicitBase},
|
|
||||||
+ {"CINDEXTEST_PRINTINGPOLICY_FULLYQUALIFIEDNAME",
|
|
||||||
+ CXPrintingPolicy_FullyQualifiedName},
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ unsigned i;
|
|
||||||
+ for (i = 0; i < sizeof(mappings) / sizeof(struct Mapping); i++) {
|
|
||||||
+ char *value = getenv(mappings[i].name);
|
|
||||||
+ if (value) {
|
|
||||||
+ clang_PrintingPolicy_setProperty(Policy, mappings[i].property,
|
|
||||||
+ (unsigned)strtoul(value, 0L, 10));
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/** \brief Returns 0 in case of success, non-zero in case of a failure. */
|
|
||||||
static int checkForErrors(CXTranslationUnit TU);
|
|
||||||
|
|
||||||
@@ -356,7 +419,11 @@ static void PrintRange(CXSourceRange R, const char *str) {
|
|
||||||
PrintExtent(stdout, begin_line, begin_column, end_line, end_column);
|
|
||||||
}
|
|
||||||
|
|
||||||
-int want_display_name = 0;
|
|
||||||
+static enum DisplayType {
|
|
||||||
+ DisplayType_Spelling,
|
|
||||||
+ DisplayType_DisplayName,
|
|
||||||
+ DisplayType_Pretty
|
|
||||||
+} wanted_display_type = DisplayType_Spelling;
|
|
||||||
|
|
||||||
static void printVersion(const char *Prefix, CXVersion Version) {
|
|
||||||
if (Version.Major < 0)
|
|
||||||
@@ -656,6 +723,24 @@ static int lineCol_cmp(const void *p1, const void *p2) {
|
|
||||||
return (int)lhs->col - (int)rhs->col;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static CXString CursorToText(CXCursor Cursor) {
|
|
||||||
+ switch (wanted_display_type) {
|
|
||||||
+ case DisplayType_Spelling:
|
|
||||||
+ return clang_getCursorSpelling(Cursor);
|
|
||||||
+ case DisplayType_DisplayName:
|
|
||||||
+ return clang_getCursorDisplayName(Cursor);
|
|
||||||
+ case DisplayType_Pretty:
|
|
||||||
+ default: {
|
|
||||||
+ CXString text;
|
|
||||||
+ CXPrintingPolicy Policy = clang_getCursorPrintingPolicy(Cursor);
|
|
||||||
+ ModifyPrintingPolicyAccordingToEnv(Policy);
|
|
||||||
+ text = clang_getCursorPrettyPrinted(Cursor, Policy);
|
|
||||||
+ clang_PrintingPolicy_dispose(Policy);
|
|
||||||
+ return text;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
|
|
||||||
CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor);
|
|
||||||
if (clang_isInvalid(Cursor.kind)) {
|
|
||||||
@@ -682,8 +767,7 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
|
|
||||||
int I;
|
|
||||||
|
|
||||||
ks = clang_getCursorKindSpelling(Cursor.kind);
|
|
||||||
- string = want_display_name? clang_getCursorDisplayName(Cursor)
|
|
||||||
- : clang_getCursorSpelling(Cursor);
|
|
||||||
+ string = CursorToText(Cursor);
|
|
||||||
printf("%s=%s", clang_getCString(ks),
|
|
||||||
clang_getCString(string));
|
|
||||||
clang_disposeString(ks);
|
|
||||||
@@ -1675,7 +1759,12 @@ static int perform_test_load(CXIndex Idx, CXTranslationUnit TU,
|
|
||||||
else if (!strcmp(filter, "all-display") ||
|
|
||||||
!strcmp(filter, "local-display")) {
|
|
||||||
ck = NULL;
|
|
||||||
- want_display_name = 1;
|
|
||||||
+ wanted_display_type = DisplayType_DisplayName;
|
|
||||||
+ }
|
|
||||||
+ else if (!strcmp(filter, "all-pretty") ||
|
|
||||||
+ !strcmp(filter, "local-pretty")) {
|
|
||||||
+ ck = NULL;
|
|
||||||
+ wanted_display_type = DisplayType_Pretty;
|
|
||||||
}
|
|
||||||
else if (!strcmp(filter, "none")) K = (enum CXCursorKind) ~0;
|
|
||||||
else if (!strcmp(filter, "category")) K = CXCursor_ObjCCategoryDecl;
|
|
||||||
@@ -1742,8 +1831,11 @@ int perform_test_load_source(int argc, const char **argv,
|
|
||||||
unsigned I;
|
|
||||||
|
|
||||||
Idx = clang_createIndex(/* excludeDeclsFromPCH */
|
|
||||||
- (!strcmp(filter, "local") ||
|
|
||||||
- !strcmp(filter, "local-display"))? 1 : 0,
|
|
||||||
+ (!strcmp(filter, "local") ||
|
|
||||||
+ !strcmp(filter, "local-display") ||
|
|
||||||
+ !strcmp(filter, "local-pretty"))
|
|
||||||
+ ? 1
|
|
||||||
+ : 0,
|
|
||||||
/* displayDiagnostics=*/1);
|
|
||||||
|
|
||||||
if ((CommentSchemaFile = parse_comments_schema(argc, argv))) {
|
|
||||||
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
|
|
||||||
index 45ee9803f2..72b14fdb53 100644
|
|
||||||
--- a/tools/clang/tools/libclang/CIndex.cpp
|
|
||||||
+++ b/tools/clang/tools/libclang/CIndex.cpp
|
|
||||||
@@ -4652,6 +4652,197 @@ CXStringSet *clang_Cursor_getCXXManglings(CXCursor C) {
|
|
||||||
return cxstring::createSet(Manglings);
|
|
||||||
}
|
|
||||||
|
|
||||||
+CXPrintingPolicy clang_getCursorPrintingPolicy(CXCursor C) {
|
|
||||||
+ if (clang_Cursor_isNull(C))
|
|
||||||
+ return 0;
|
|
||||||
+ return new PrintingPolicy(getCursorContext(C).getPrintingPolicy());
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void clang_PrintingPolicy_dispose(CXPrintingPolicy Policy) {
|
|
||||||
+ if (Policy)
|
|
||||||
+ delete static_cast<PrintingPolicy *>(Policy);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+unsigned
|
|
||||||
+clang_PrintingPolicy_getProperty(CXPrintingPolicy Policy,
|
|
||||||
+ enum CXPrintingPolicyProperty Property) {
|
|
||||||
+ if (!Policy)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ PrintingPolicy *P = static_cast<PrintingPolicy *>(Policy);
|
|
||||||
+ switch (Property) {
|
|
||||||
+ case CXPrintingPolicy_Indentation:
|
|
||||||
+ return P->Indentation;
|
|
||||||
+ case CXPrintingPolicy_SuppressSpecifiers:
|
|
||||||
+ return P->SuppressSpecifiers;
|
|
||||||
+ case CXPrintingPolicy_SuppressTagKeyword:
|
|
||||||
+ return P->SuppressTagKeyword;
|
|
||||||
+ case CXPrintingPolicy_IncludeTagDefinition:
|
|
||||||
+ return P->IncludeTagDefinition;
|
|
||||||
+ case CXPrintingPolicy_SuppressScope:
|
|
||||||
+ return P->SuppressScope;
|
|
||||||
+ case CXPrintingPolicy_SuppressUnwrittenScope:
|
|
||||||
+ return P->SuppressUnwrittenScope;
|
|
||||||
+ case CXPrintingPolicy_SuppressInitializers:
|
|
||||||
+ return P->SuppressInitializers;
|
|
||||||
+ case CXPrintingPolicy_ConstantArraySizeAsWritten:
|
|
||||||
+ return P->ConstantArraySizeAsWritten;
|
|
||||||
+ case CXPrintingPolicy_AnonymousTagLocations:
|
|
||||||
+ return P->AnonymousTagLocations;
|
|
||||||
+ case CXPrintingPolicy_SuppressStrongLifetime:
|
|
||||||
+ return P->SuppressStrongLifetime;
|
|
||||||
+ case CXPrintingPolicy_SuppressLifetimeQualifiers:
|
|
||||||
+ return P->SuppressLifetimeQualifiers;
|
|
||||||
+ case CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors:
|
|
||||||
+ return P->SuppressTemplateArgsInCXXConstructors;
|
|
||||||
+ case CXPrintingPolicy_Bool:
|
|
||||||
+ return P->Bool;
|
|
||||||
+ case CXPrintingPolicy_Restrict:
|
|
||||||
+ return P->Restrict;
|
|
||||||
+ case CXPrintingPolicy_Alignof:
|
|
||||||
+ return P->Alignof;
|
|
||||||
+ case CXPrintingPolicy_UnderscoreAlignof:
|
|
||||||
+ return P->UnderscoreAlignof;
|
|
||||||
+ case CXPrintingPolicy_UseVoidForZeroParams:
|
|
||||||
+ return P->UseVoidForZeroParams;
|
|
||||||
+ case CXPrintingPolicy_TerseOutput:
|
|
||||||
+ return P->TerseOutput;
|
|
||||||
+ case CXPrintingPolicy_PolishForDeclaration:
|
|
||||||
+ return P->PolishForDeclaration;
|
|
||||||
+ case CXPrintingPolicy_Half:
|
|
||||||
+ return P->Half;
|
|
||||||
+ case CXPrintingPolicy_MSWChar:
|
|
||||||
+ return P->MSWChar;
|
|
||||||
+ case CXPrintingPolicy_IncludeNewlines:
|
|
||||||
+ return P->IncludeNewlines;
|
|
||||||
+ case CXPrintingPolicy_MSVCFormatting:
|
|
||||||
+ return P->MSVCFormatting;
|
|
||||||
+ case CXPrintingPolicy_ConstantsAsWritten:
|
|
||||||
+ // Ops, not yet there in clang 5.0 and we do not need it.
|
|
||||||
+ return 0;
|
|
||||||
+ case CXPrintingPolicy_SuppressImplicitBase:
|
|
||||||
+ // Ops, not yet there in clang 5.0 and we do not need it.
|
|
||||||
+ return 0;
|
|
||||||
+ case CXPrintingPolicy_FullyQualifiedName:
|
|
||||||
+ return P->FullyQualifiedName;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ assert(false && "Invalid CXPrintingPolicyProperty");
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void clang_PrintingPolicy_setProperty(CXPrintingPolicy Policy,
|
|
||||||
+ enum CXPrintingPolicyProperty Property,
|
|
||||||
+ unsigned Value) {
|
|
||||||
+ if (!Policy)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ PrintingPolicy *P = static_cast<PrintingPolicy *>(Policy);
|
|
||||||
+ switch (Property) {
|
|
||||||
+ case CXPrintingPolicy_Indentation:
|
|
||||||
+ P->Indentation = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_SuppressSpecifiers:
|
|
||||||
+ P->SuppressSpecifiers = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_SuppressTagKeyword:
|
|
||||||
+ P->SuppressTagKeyword = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_IncludeTagDefinition:
|
|
||||||
+ P->IncludeTagDefinition = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_SuppressScope:
|
|
||||||
+ P->SuppressScope = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_SuppressUnwrittenScope:
|
|
||||||
+ P->SuppressUnwrittenScope = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_SuppressInitializers:
|
|
||||||
+ P->SuppressInitializers = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_ConstantArraySizeAsWritten:
|
|
||||||
+ P->ConstantArraySizeAsWritten = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_AnonymousTagLocations:
|
|
||||||
+ P->AnonymousTagLocations = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_SuppressStrongLifetime:
|
|
||||||
+ P->SuppressStrongLifetime = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_SuppressLifetimeQualifiers:
|
|
||||||
+ P->SuppressLifetimeQualifiers = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors:
|
|
||||||
+ P->SuppressTemplateArgsInCXXConstructors = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_Bool:
|
|
||||||
+ P->Bool = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_Restrict:
|
|
||||||
+ P->Restrict = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_Alignof:
|
|
||||||
+ P->Alignof = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_UnderscoreAlignof:
|
|
||||||
+ P->UnderscoreAlignof = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_UseVoidForZeroParams:
|
|
||||||
+ P->UseVoidForZeroParams = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_TerseOutput:
|
|
||||||
+ P->TerseOutput = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_PolishForDeclaration:
|
|
||||||
+ P->PolishForDeclaration = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_Half:
|
|
||||||
+ P->Half = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_MSWChar:
|
|
||||||
+ P->MSWChar = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_IncludeNewlines:
|
|
||||||
+ P->IncludeNewlines = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_MSVCFormatting:
|
|
||||||
+ P->MSVCFormatting = Value;
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_ConstantsAsWritten:
|
|
||||||
+ // Ops, not yet there in clang 5.0 and we do not need it.
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_SuppressImplicitBase:
|
|
||||||
+ // Ops, not yet there in clang 5.0 and we do not need it.
|
|
||||||
+ return;
|
|
||||||
+ case CXPrintingPolicy_FullyQualifiedName:
|
|
||||||
+ P->FullyQualifiedName = Value;
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ assert(false && "Invalid CXPrintingPolicyProperty");
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+CXString clang_getCursorPrettyPrinted(CXCursor C, CXPrintingPolicy cxPolicy) {
|
|
||||||
+ if (clang_Cursor_isNull(C))
|
|
||||||
+ return cxstring::createEmpty();
|
|
||||||
+
|
|
||||||
+ if (clang_isDeclaration(C.kind)) {
|
|
||||||
+ const Decl *D = getCursorDecl(C);
|
|
||||||
+ if (!D)
|
|
||||||
+ return cxstring::createEmpty();
|
|
||||||
+
|
|
||||||
+ SmallString<128> Str;
|
|
||||||
+ llvm::raw_svector_ostream OS(Str);
|
|
||||||
+ PrintingPolicy *UserPolicy = static_cast<PrintingPolicy *>(cxPolicy);
|
|
||||||
+ D->print(OS, UserPolicy ? *UserPolicy
|
|
||||||
+ : getCursorContext(C).getPrintingPolicy());
|
|
||||||
+
|
|
||||||
+ return cxstring::createDup(OS.str());
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return cxstring::createEmpty();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
CXString clang_getCursorDisplayName(CXCursor C) {
|
|
||||||
if (!clang_isDeclaration(C.kind))
|
|
||||||
return clang_getCursorSpelling(C);
|
|
||||||
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
|
|
||||||
index c788abb881..ed4773b132 100644
|
|
||||||
--- a/tools/clang/tools/libclang/libclang.exports
|
|
||||||
+++ b/tools/clang/tools/libclang/libclang.exports
|
|
||||||
@@ -175,6 +175,8 @@ clang_getCursorAvailability
|
|
||||||
clang_getCursorCompletionString
|
|
||||||
clang_getCursorDefinition
|
|
||||||
clang_getCursorDisplayName
|
|
||||||
+clang_getCursorPrintingPolicy
|
|
||||||
+clang_getCursorPrettyPrinted
|
|
||||||
clang_getCursorExtent
|
|
||||||
clang_getCursorExceptionSpecificationType
|
|
||||||
clang_getCursorKind
|
|
||||||
@@ -355,3 +357,6 @@ clang_EvalResult_isUnsignedInt
|
|
||||||
clang_EvalResult_getAsDouble
|
|
||||||
clang_EvalResult_getAsStr
|
|
||||||
clang_EvalResult_dispose
|
|
||||||
+clang_PrintingPolicy_getProperty
|
|
||||||
+clang_PrintingPolicy_setProperty
|
|
||||||
+clang_PrintingPolicy_dispose
|
|
||||||
diff --git a/unittests/libclang/LibclangTest.cpp b/unittests/libclang/LibclangTest.cpp
|
|
||||||
index f2a96d6be6..342fbd5279 100644
|
|
||||||
--- a/tools/clang/unittests/libclang/LibclangTest.cpp
|
|
||||||
+++ b/tools/clang/unittests/libclang/LibclangTest.cpp
|
|
||||||
@@ -572,3 +572,35 @@ TEST_F(LibclangReparseTest, clang_parseTranslationUnit2FullArgv) {
|
|
||||||
EXPECT_EQ(0U, clang_getNumDiagnostics(ClangTU));
|
|
||||||
DisplayDiagnostics();
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+class LibclangPrintingPolicyTest : public LibclangParseTest {
|
|
||||||
+public:
|
|
||||||
+ CXPrintingPolicy Policy = nullptr;
|
|
||||||
+
|
|
||||||
+ void SetUp() override {
|
|
||||||
+ LibclangParseTest::SetUp();
|
|
||||||
+ std::string File = "file.cpp";
|
|
||||||
+ WriteFile(File, "int i;\n");
|
|
||||||
+ ClangTU = clang_parseTranslationUnit(Index, File.c_str(), nullptr, 0,
|
|
||||||
+ nullptr, 0, TUFlags);
|
|
||||||
+ CXCursor TUCursor = clang_getTranslationUnitCursor(ClangTU);
|
|
||||||
+ Policy = clang_getCursorPrintingPolicy(TUCursor);
|
|
||||||
+ }
|
|
||||||
+ void TearDown() override {
|
|
||||||
+ clang_PrintingPolicy_dispose(Policy);
|
|
||||||
+ LibclangParseTest::TearDown();
|
|
||||||
+ }
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+TEST_F(LibclangPrintingPolicyTest, SetAndGetProperties) {
|
|
||||||
+ for (unsigned Value = 0; Value < 2; ++Value) {
|
|
||||||
+ for (int I = 0; I < CXPrintingPolicy_LastProperty; ++I) {
|
|
||||||
+ auto Property = static_cast<enum CXPrintingPolicyProperty>(I);
|
|
||||||
+ if (Property == CXPrintingPolicy_ConstantsAsWritten || Property == CXPrintingPolicy_SuppressImplicitBase)
|
|
||||||
+ continue; // These are not yet in clang 5.0.
|
|
||||||
+
|
|
||||||
+ clang_PrintingPolicy_setProperty(Policy, Property, Value);
|
|
||||||
+ EXPECT_EQ(Value, clang_PrintingPolicy_getProperty(Policy, Property));
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
--- a/tools/clang/include/clang/Sema/Sema.h
|
|
||||||
+++ b/tools/clang/include/clang/Sema/Sema.h
|
|
||||||
@@ -2707,7 +2707,8 @@
|
|
||||||
OverloadCandidateSet &CandidateSet,
|
|
||||||
TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
|
|
||||||
bool SuppressUserConversions = false,
|
|
||||||
- bool PartialOverloading = false);
|
|
||||||
+ bool PartialOverloading = false,
|
|
||||||
+ bool FirstArgumentIsBase = false);
|
|
||||||
void AddMethodCandidate(DeclAccessPair FoundDecl,
|
|
||||||
QualType ObjectType,
|
|
||||||
Expr::Classification ObjectClassification,
|
|
||||||
--- a/tools/clang/lib/Sema/SemaCodeComplete.cpp
|
|
||||||
+++ b/tools/clang/lib/Sema/SemaCodeComplete.cpp
|
|
||||||
@@ -4396,9 +4396,11 @@
|
|
||||||
ArgExprs.append(Args.begin(), Args.end());
|
|
||||||
UnresolvedSet<8> Decls;
|
|
||||||
Decls.append(UME->decls_begin(), UME->decls_end());
|
|
||||||
+ const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
|
|
||||||
AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
|
|
||||||
/*SuppressUsedConversions=*/false,
|
|
||||||
- /*PartialOverloading=*/true);
|
|
||||||
+ /*PartialOverloading=*/true,
|
|
||||||
+ FirstArgumentIsBase);
|
|
||||||
} else {
|
|
||||||
FunctionDecl *FD = nullptr;
|
|
||||||
if (auto MCE = dyn_cast<MemberExpr>(NakedFn))
|
|
||||||
--- a/tools/clang/lib/Sema/SemaOverload.cpp
|
|
||||||
+++ b/tools/clang/lib/Sema/SemaOverload.cpp
|
|
||||||
@@ -6343,24 +6343,36 @@
|
|
||||||
OverloadCandidateSet& CandidateSet,
|
|
||||||
TemplateArgumentListInfo *ExplicitTemplateArgs,
|
|
||||||
bool SuppressUserConversions,
|
|
||||||
- bool PartialOverloading) {
|
|
||||||
+ bool PartialOverloading,
|
|
||||||
+ bool FirstArgumentIsBase) {
|
|
||||||
for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
|
|
||||||
NamedDecl *D = F.getDecl()->getUnderlyingDecl();
|
|
||||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
|
||||||
+ ArrayRef<Expr *> FunctionArgs = Args;
|
|
||||||
if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) {
|
|
||||||
QualType ObjectType;
|
|
||||||
Expr::Classification ObjectClassification;
|
|
||||||
- if (Expr *E = Args[0]) {
|
|
||||||
- // Use the explit base to restrict the lookup:
|
|
||||||
- ObjectType = E->getType();
|
|
||||||
- ObjectClassification = E->Classify(Context);
|
|
||||||
- } // .. else there is an implit base.
|
|
||||||
+ if (Args.size() > 0) {
|
|
||||||
+ if (Expr *E = Args[0]) {
|
|
||||||
+ // Use the explit base to restrict the lookup:
|
|
||||||
+ ObjectType = E->getType();
|
|
||||||
+ ObjectClassification = E->Classify(Context);
|
|
||||||
+ } // .. else there is an implit base.
|
|
||||||
+ FunctionArgs = Args.slice(1);
|
|
||||||
+ }
|
|
||||||
AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
|
|
||||||
cast<CXXMethodDecl>(FD)->getParent(), ObjectType,
|
|
||||||
- ObjectClassification, Args.slice(1), CandidateSet,
|
|
||||||
+ ObjectClassification, FunctionArgs, CandidateSet,
|
|
||||||
SuppressUserConversions, PartialOverloading);
|
|
||||||
} else {
|
|
||||||
- AddOverloadCandidate(FD, F.getPair(), Args, CandidateSet,
|
|
||||||
+ // Slice the first argument (which is the base) when we access
|
|
||||||
+ // static method as non-static
|
|
||||||
+ if (Args.size() > 0 && (!Args[0] || (FirstArgumentIsBase && isa<CXXMethodDecl>(FD) &&
|
|
||||||
+ !isa<CXXConstructorDecl>(FD)))) {
|
|
||||||
+ assert(cast<CXXMethodDecl>(FD)->isStatic());
|
|
||||||
+ FunctionArgs = Args.slice(1);
|
|
||||||
+ }
|
|
||||||
+ AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet,
|
|
||||||
SuppressUserConversions, PartialOverloading);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
--- a/tools/clang/test/Index/complete-call.cpp
|
|
||||||
+++ b/tools/clang/test/Index/complete-call.cpp
|
|
||||||
@@ -94,6 +94,24 @@
|
|
||||||
s.foo_7(42,);
|
|
||||||
}
|
|
||||||
|
|
||||||
+struct Bar {
|
|
||||||
+ static void foo_1();
|
|
||||||
+ void foo_1(float);
|
|
||||||
+ static void foo_1(int);
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+void test() {
|
|
||||||
+ Bar::foo_1();
|
|
||||||
+ Bar b;
|
|
||||||
+ b.foo_1();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+struct Bar2 : public Bar {
|
|
||||||
+ Bar2() {
|
|
||||||
+ Bar::foo_1();
|
|
||||||
+ }
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
// RUN: c-index-test -code-completion-at=%s:47:9 %s | FileCheck -check-prefix=CHECK-CC1 %s
|
|
||||||
// CHECK-CC1: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1)
|
|
||||||
// CHECK-CC1: Completion contexts:
|
|
||||||
@@ -803,3 +821,46 @@
|
|
||||||
// CHECK-CC59-NEXT: Class name
|
|
||||||
// CHECK-CC59-NEXT: Nested name specifier
|
|
||||||
// CHECK-CC59-NEXT: Objective-C interface
|
|
||||||
+
|
|
||||||
+// RUN: c-index-test -code-completion-at=%s:104:14 %s | FileCheck -check-prefix=CHECK-CC60 %s
|
|
||||||
+// CHECK-CC60: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1)
|
|
||||||
+// CHECK-CC60: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1)
|
|
||||||
+// CHECK-CC60: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1)
|
|
||||||
+// CHECK-CC60: Completion contexts:
|
|
||||||
+// CHECK-CC60-NEXT: Any type
|
|
||||||
+// CHECK-CC60-NEXT: Any value
|
|
||||||
+// CHECK-CC60-NEXT: Enum tag
|
|
||||||
+// CHECK-CC60-NEXT: Union tag
|
|
||||||
+// CHECK-CC60-NEXT: Struct tag
|
|
||||||
+// CHECK-CC60-NEXT: Class name
|
|
||||||
+// CHECK-CC60-NEXT: Nested name specifier
|
|
||||||
+// CHECK-CC60-NEXT: Objective-C interface
|
|
||||||
+
|
|
||||||
+// RUN: c-index-test -code-completion-at=%s:106:11 %s | FileCheck -check-prefix=CHECK-CC61 %s
|
|
||||||
+// CHECK-CC61: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1)
|
|
||||||
+// CHECK-CC61: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1)
|
|
||||||
+// CHECK-CC61: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1)
|
|
||||||
+// CHECK-CC61: Completion contexts:
|
|
||||||
+// CHECK-CC61-NEXT: Any type
|
|
||||||
+// CHECK-CC61-NEXT: Any value
|
|
||||||
+// CHECK-CC61-NEXT: Enum tag
|
|
||||||
+// CHECK-CC61-NEXT: Union tag
|
|
||||||
+// CHECK-CC61-NEXT: Struct tag
|
|
||||||
+// CHECK-CC61-NEXT: Class name
|
|
||||||
+// CHECK-CC61-NEXT: Nested name specifier
|
|
||||||
+// CHECK-CC61-NEXT: Objective-C interface
|
|
||||||
+
|
|
||||||
+// RUN: c-index-test -code-completion-at=%s:111:16 %s | FileCheck -check-prefix=CHECK-CC62 %s
|
|
||||||
+// CHECK-CC62: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1)
|
|
||||||
+// CHECK-CC62: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1)
|
|
||||||
+// CHECK-CC62: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1)
|
|
||||||
+// CHECK-CC62: Completion contexts:
|
|
||||||
+// CHECK-CC62-NEXT: Any type
|
|
||||||
+// CHECK-CC62-NEXT: Any value
|
|
||||||
+// CHECK-CC62-NEXT: Enum tag
|
|
||||||
+// CHECK-CC62-NEXT: Union tag
|
|
||||||
+// CHECK-CC62-NEXT: Struct tag
|
|
||||||
+// CHECK-CC62-NEXT: Class name
|
|
||||||
+// CHECK-CC62-NEXT: Nested name specifier
|
|
||||||
+// CHECK-CC62-NEXT: Objective-C interface
|
|
||||||
+
|
|
||||||
@@ -1,165 +0,0 @@
|
|||||||
diff --git a/tools/clang/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
|
|
||||||
index 1b07ec60ce..46ed08d1cf 100644
|
|
||||||
--- a/tools/clang/lib/Sema/SemaOverload.cpp
|
|
||||||
+++ b/tools/clang/lib/Sema/SemaOverload.cpp
|
|
||||||
@@ -6321,57 +6321,56 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
|
|
||||||
bool FirstArgumentIsBase) {
|
|
||||||
for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
|
|
||||||
NamedDecl *D = F.getDecl()->getUnderlyingDecl();
|
|
||||||
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
|
||||||
- ArrayRef<Expr *> FunctionArgs = Args;
|
|
||||||
- if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) {
|
|
||||||
- QualType ObjectType;
|
|
||||||
- Expr::Classification ObjectClassification;
|
|
||||||
- if (Args.size() > 0) {
|
|
||||||
- if (Expr *E = Args[0]) {
|
|
||||||
- // Use the explit base to restrict the lookup:
|
|
||||||
- ObjectType = E->getType();
|
|
||||||
- ObjectClassification = E->Classify(Context);
|
|
||||||
- } // .. else there is an implit base.
|
|
||||||
- FunctionArgs = Args.slice(1);
|
|
||||||
- }
|
|
||||||
- AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
|
|
||||||
- cast<CXXMethodDecl>(FD)->getParent(), ObjectType,
|
|
||||||
- ObjectClassification, FunctionArgs, CandidateSet,
|
|
||||||
- SuppressUserConversions, PartialOverloading);
|
|
||||||
- } else {
|
|
||||||
- // Slice the first argument (which is the base) when we access
|
|
||||||
- // static method as non-static
|
|
||||||
- if (Args.size() > 0 && (!Args[0] || (FirstArgumentIsBase && isa<CXXMethodDecl>(FD) &&
|
|
||||||
- !isa<CXXConstructorDecl>(FD)))) {
|
|
||||||
- assert(cast<CXXMethodDecl>(FD)->isStatic());
|
|
||||||
- FunctionArgs = Args.slice(1);
|
|
||||||
- }
|
|
||||||
- AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet,
|
|
||||||
- SuppressUserConversions, PartialOverloading);
|
|
||||||
- }
|
|
||||||
- } else {
|
|
||||||
- FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(D);
|
|
||||||
- if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) &&
|
|
||||||
- !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic()) {
|
|
||||||
- QualType ObjectType;
|
|
||||||
- Expr::Classification ObjectClassification;
|
|
||||||
+ ArrayRef<Expr *> FunctionArgs = Args;
|
|
||||||
+
|
|
||||||
+ FunctionTemplateDecl *FunTmpl = nullptr;
|
|
||||||
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
|
|
||||||
+
|
|
||||||
+ const bool IsTemplate = FD ? false : true;
|
|
||||||
+ if (IsTemplate) {
|
|
||||||
+ FunTmpl = cast<FunctionTemplateDecl>(D);
|
|
||||||
+ FD = FunTmpl->getTemplatedDecl();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) {
|
|
||||||
+ QualType ObjectType;
|
|
||||||
+ Expr::Classification ObjectClassification;
|
|
||||||
+ if (Args.size() > 0) {
|
|
||||||
if (Expr *E = Args[0]) {
|
|
||||||
// Use the explit base to restrict the lookup:
|
|
||||||
ObjectType = E->getType();
|
|
||||||
ObjectClassification = E->Classify(Context);
|
|
||||||
} // .. else there is an implit base.
|
|
||||||
+ FunctionArgs = Args.slice(1);
|
|
||||||
+ }
|
|
||||||
+ if (IsTemplate)
|
|
||||||
AddMethodTemplateCandidate(
|
|
||||||
FunTmpl, F.getPair(),
|
|
||||||
cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
|
|
||||||
ExplicitTemplateArgs, ObjectType, ObjectClassification,
|
|
||||||
- Args.slice(1), CandidateSet, SuppressUserConversions,
|
|
||||||
+ FunctionArgs, CandidateSet, SuppressUserConversions,
|
|
||||||
PartialOverloading);
|
|
||||||
- } else {
|
|
||||||
- AddTemplateOverloadCandidate(FunTmpl, F.getPair(),
|
|
||||||
- ExplicitTemplateArgs, Args,
|
|
||||||
- CandidateSet, SuppressUserConversions,
|
|
||||||
- PartialOverloading);
|
|
||||||
+ else
|
|
||||||
+ AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
|
|
||||||
+ cast<CXXMethodDecl>(FD)->getParent(), ObjectType,
|
|
||||||
+ ObjectClassification, FunctionArgs, CandidateSet,
|
|
||||||
+ SuppressUserConversions, PartialOverloading);
|
|
||||||
+ } else {
|
|
||||||
+ // Slice the first argument (which is the base) when we access
|
|
||||||
+ // static method as non-static
|
|
||||||
+ if (Args.size() > 0 &&
|
|
||||||
+ (!Args[0] || (FirstArgumentIsBase && isa<CXXMethodDecl>(FD) &&
|
|
||||||
+ !isa<CXXConstructorDecl>(FD)))) {
|
|
||||||
+ assert(cast<CXXMethodDecl>(FD)->isStatic());
|
|
||||||
+ FunctionArgs = Args.slice(1);
|
|
||||||
}
|
|
||||||
+ if (IsTemplate)
|
|
||||||
+ AddTemplateOverloadCandidate(
|
|
||||||
+ FunTmpl, F.getPair(), ExplicitTemplateArgs, FunctionArgs,
|
|
||||||
+ CandidateSet, SuppressUserConversions, PartialOverloading);
|
|
||||||
+ else
|
|
||||||
+ AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet,
|
|
||||||
+ SuppressUserConversions, PartialOverloading);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
diff --git a/tools/clang/test/Index/complete-call.cpp b/test/Index/complete-call.cpp
|
|
||||||
index ca116485ac..35f2009066 100644
|
|
||||||
--- a/tools/clang/test/Index/complete-call.cpp
|
|
||||||
+++ b/tools/clang/test/Index/complete-call.cpp
|
|
||||||
@@ -112,6 +112,33 @@ struct Bar2 : public Bar {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
+struct BarTemplates {
|
|
||||||
+ static void foo_1() {}
|
|
||||||
+ void foo_1(float) {}
|
|
||||||
+ static void foo_1(int) {}
|
|
||||||
+
|
|
||||||
+ template<class T1, class T2>
|
|
||||||
+ static void foo_1(T1 a, T2 b) { a + b; }
|
|
||||||
+
|
|
||||||
+ template<class T1, class T2>
|
|
||||||
+ void foo_1(T1 a, T2 b, float c) { a + b + c; }
|
|
||||||
+
|
|
||||||
+ template<class T1, class T2>
|
|
||||||
+ static void foo_1(T2 a, int b, T1 c) { a + b + c; }
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+void testTemplates() {
|
|
||||||
+ BarTemplates::foo_1();
|
|
||||||
+ BarTemplates b;
|
|
||||||
+ b.foo_1();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+struct Bar2Template : public BarTemplates {
|
|
||||||
+ Bar2Template() {
|
|
||||||
+ BarTemplates::foo_1();
|
|
||||||
+ }
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
// RUN: c-index-test -code-completion-at=%s:47:9 %s | FileCheck -check-prefix=CHECK-CC1 %s
|
|
||||||
// CHECK-CC1: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1)
|
|
||||||
// CHECK-CC1: Completion contexts:
|
|
||||||
@@ -864,3 +891,25 @@ struct Bar2 : public Bar {
|
|
||||||
// CHECK-CC62-NEXT: Nested name specifier
|
|
||||||
// CHECK-CC62-NEXT: Objective-C interface
|
|
||||||
|
|
||||||
+// RUN: c-index-test -code-completion-at=%s:131:23 %s | FileCheck -check-prefix=CHECK-CC63 %s
|
|
||||||
+// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1)
|
|
||||||
+// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1)
|
|
||||||
+// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1)
|
|
||||||
+// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1)
|
|
||||||
+// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{Comma , }{Placeholder float c}{RightParen )} (1)
|
|
||||||
+// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1)
|
|
||||||
+
|
|
||||||
+// RUN: c-index-test -code-completion-at=%s:133:11 %s | FileCheck -check-prefix=CHECK-CC64 %s
|
|
||||||
+// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1)
|
|
||||||
+// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1)
|
|
||||||
+// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1)
|
|
||||||
+// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1)
|
|
||||||
+// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1)
|
|
||||||
+
|
|
||||||
+// RUN: c-index-test -code-completion-at=%s:138:25 %s | FileCheck -check-prefix=CHECK-CC65 %s
|
|
||||||
+// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1)
|
|
||||||
+// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1)
|
|
||||||
+// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1)
|
|
||||||
+// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1)
|
|
||||||
+// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{Comma , }{Placeholder float c}{RightParen )} (1)
|
|
||||||
+// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1)
|
|
||||||
@@ -1,739 +0,0 @@
|
|||||||
diff --git a/tools/clang/include/clang/AST/ASTContext.h b/tools/clang/include/clang/AST/ASTContext.h
|
|
||||||
index 703f588c56..d7beffa25e 100644
|
|
||||||
--- a/tools/clang/include/clang/AST/ASTContext.h
|
|
||||||
+++ b/tools/clang/include/clang/AST/ASTContext.h
|
|
||||||
@@ -2072,6 +2072,10 @@ public:
|
|
||||||
void CollectInheritedProtocols(const Decl *CDecl,
|
|
||||||
llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols);
|
|
||||||
|
|
||||||
+ /// \brief Return true if the specified type has unique object representations
|
|
||||||
+ /// according to (C++17 [meta.unary.prop]p9)
|
|
||||||
+ bool hasUniqueObjectRepresentations(QualType Ty) const;
|
|
||||||
+
|
|
||||||
//===--------------------------------------------------------------------===//
|
|
||||||
// Type Operators
|
|
||||||
//===--------------------------------------------------------------------===//
|
|
||||||
diff --git a/tools/clang/include/clang/Basic/TokenKinds.def b/tools/clang/include/clang/Basic/TokenKinds.def
|
|
||||||
index be67663a10..90ac33b9ea 100644
|
|
||||||
--- a/tools/clang/include/clang/Basic/TokenKinds.def
|
|
||||||
+++ b/tools/clang/include/clang/Basic/TokenKinds.def
|
|
||||||
@@ -448,6 +448,8 @@ TYPE_TRAIT_1(__is_pod, IsPOD, KEYCXX)
|
|
||||||
TYPE_TRAIT_1(__is_polymorphic, IsPolymorphic, KEYCXX)
|
|
||||||
TYPE_TRAIT_1(__is_trivial, IsTrivial, KEYCXX)
|
|
||||||
TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
|
|
||||||
+TYPE_TRAIT_1(__has_unique_object_representations,
|
|
||||||
+ HasUniqueObjectRepresentations, KEYCXX)
|
|
||||||
|
|
||||||
// Clang-only C++ Type Traits
|
|
||||||
TYPE_TRAIT_N(__is_trivially_constructible, IsTriviallyConstructible, KEYCXX)
|
|
||||||
diff --git a/tools/clang/include/clang/Basic/TypeTraits.h b/tools/clang/include/clang/Basic/TypeTraits.h
|
|
||||||
index 6aadf795d8..8ecd63f9c3 100644
|
|
||||||
--- a/tools/clang/include/clang/Basic/TypeTraits.h
|
|
||||||
+++ b/tools/clang/include/clang/Basic/TypeTraits.h
|
|
||||||
@@ -70,7 +70,8 @@ namespace clang {
|
|
||||||
UTT_IsUnsigned,
|
|
||||||
UTT_IsVoid,
|
|
||||||
UTT_IsVolatile,
|
|
||||||
- UTT_Last = UTT_IsVolatile,
|
|
||||||
+ UTT_HasUniqueObjectRepresentations,
|
|
||||||
+ UTT_Last = UTT_HasUniqueObjectRepresentations,
|
|
||||||
BTT_IsBaseOf,
|
|
||||||
BTT_IsConvertible,
|
|
||||||
BTT_IsConvertibleTo,
|
|
||||||
diff --git a/tools/clang/lib/AST/ASTContext.cpp b/tools/clang/lib/AST/ASTContext.cpp
|
|
||||||
index c60373c5a9..1ce7d51857 100644
|
|
||||||
--- a/tools/clang/lib/AST/ASTContext.cpp
|
|
||||||
+++ b/tools/clang/lib/AST/ASTContext.cpp
|
|
||||||
@@ -1823,7 +1823,9 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
|
|
||||||
}
|
|
||||||
case Type::MemberPointer: {
|
|
||||||
const MemberPointerType *MPT = cast<MemberPointerType>(T);
|
|
||||||
- std::tie(Width, Align) = ABI->getMemberPointerWidthAndAlign(MPT);
|
|
||||||
+ CXXABI::MemberPointerInfo MPI = ABI->getMemberPointerInfo(MPT);
|
|
||||||
+ Width = MPI.Width;
|
|
||||||
+ Align = MPI.Align;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Type::Complex: {
|
|
||||||
@@ -2107,6 +2109,171 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+static bool unionHasUniqueObjectRepresentations(const ASTContext &Context,
|
|
||||||
+ const RecordDecl *RD) {
|
|
||||||
+ assert(RD->isUnion() && "Must be union type");
|
|
||||||
+ CharUnits UnionSize = Context.getTypeSizeInChars(RD->getTypeForDecl());
|
|
||||||
+
|
|
||||||
+ for (const auto *Field : RD->fields()) {
|
|
||||||
+ if (!Context.hasUniqueObjectRepresentations(Field->getType()))
|
|
||||||
+ return false;
|
|
||||||
+ CharUnits FieldSize = Context.getTypeSizeInChars(Field->getType());
|
|
||||||
+ if (FieldSize != UnionSize)
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+ return !RD->field_empty();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+bool isStructEmpty(QualType Ty) {
|
|
||||||
+ const RecordDecl *RD = Ty->castAs<RecordType>()->getDecl();
|
|
||||||
+
|
|
||||||
+ if (!RD->field_empty())
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RD))
|
|
||||||
+ return ClassDecl->isEmpty();
|
|
||||||
+
|
|
||||||
+ return true;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static llvm::Optional<int64_t>
|
|
||||||
+structHasUniqueObjectRepresentations(const ASTContext &Context,
|
|
||||||
+ const RecordDecl *RD) {
|
|
||||||
+ assert(!RD->isUnion() && "Must be struct/class type");
|
|
||||||
+ const auto &Layout = Context.getASTRecordLayout(RD);
|
|
||||||
+
|
|
||||||
+ int64_t CurOffsetInBits = 0;
|
|
||||||
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RD)) {
|
|
||||||
+ if (ClassDecl->isDynamicClass())
|
|
||||||
+ return llvm::None;
|
|
||||||
+
|
|
||||||
+ SmallVector<std::pair<QualType, int64_t>, 4> Bases;
|
|
||||||
+ for (const auto Base : ClassDecl->bases()) {
|
|
||||||
+ // Empty types can be inherited from, and non-empty types can potentially
|
|
||||||
+ // have tail padding, so just make sure there isn't an error.
|
|
||||||
+ if (!isStructEmpty(Base.getType())) {
|
|
||||||
+ llvm::Optional<int64_t> Size = structHasUniqueObjectRepresentations(
|
|
||||||
+ Context, Base.getType()->getAs<RecordType>()->getDecl());
|
|
||||||
+ if (!Size)
|
|
||||||
+ return llvm::None;
|
|
||||||
+ Bases.emplace_back(Base.getType(), Size.getValue());
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ std::sort(
|
|
||||||
+ Bases.begin(), Bases.end(), [&](const std::pair<QualType, int64_t> &L,
|
|
||||||
+ const std::pair<QualType, int64_t> &R) {
|
|
||||||
+ return Layout.getBaseClassOffset(L.first->getAsCXXRecordDecl()) <
|
|
||||||
+ Layout.getBaseClassOffset(R.first->getAsCXXRecordDecl());
|
|
||||||
+ });
|
|
||||||
+
|
|
||||||
+ for (const auto Base : Bases) {
|
|
||||||
+ int64_t BaseOffset = Context.toBits(
|
|
||||||
+ Layout.getBaseClassOffset(Base.first->getAsCXXRecordDecl()));
|
|
||||||
+ int64_t BaseSize = Base.second;
|
|
||||||
+ if (BaseOffset != CurOffsetInBits)
|
|
||||||
+ return llvm::None;
|
|
||||||
+ CurOffsetInBits = BaseOffset + BaseSize;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ for (const auto *Field : RD->fields()) {
|
|
||||||
+ if (!Field->getType()->isReferenceType() &&
|
|
||||||
+ !Context.hasUniqueObjectRepresentations(Field->getType()))
|
|
||||||
+ return llvm::None;
|
|
||||||
+
|
|
||||||
+ int64_t FieldSizeInBits =
|
|
||||||
+ Context.toBits(Context.getTypeSizeInChars(Field->getType()));
|
|
||||||
+ if (Field->isBitField()) {
|
|
||||||
+ int64_t BitfieldSize = Field->getBitWidthValue(Context);
|
|
||||||
+
|
|
||||||
+ if (BitfieldSize > FieldSizeInBits)
|
|
||||||
+ return llvm::None;
|
|
||||||
+ FieldSizeInBits = BitfieldSize;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ int64_t FieldOffsetInBits = Context.getFieldOffset(Field);
|
|
||||||
+
|
|
||||||
+ if (FieldOffsetInBits != CurOffsetInBits)
|
|
||||||
+ return llvm::None;
|
|
||||||
+
|
|
||||||
+ CurOffsetInBits = FieldSizeInBits + FieldOffsetInBits;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return CurOffsetInBits;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+bool ASTContext::hasUniqueObjectRepresentations(QualType Ty) const {
|
|
||||||
+ // C++17 [meta.unary.prop]:
|
|
||||||
+ // The predicate condition for a template specialization
|
|
||||||
+ // has_unique_object_representations<T> shall be
|
|
||||||
+ // satisfied if and only if:
|
|
||||||
+ // (9.1) - T is trivially copyable, and
|
|
||||||
+ // (9.2) - any two objects of type T with the same value have the same
|
|
||||||
+ // object representation, where two objects
|
|
||||||
+ // of array or non-union class type are considered to have the same value
|
|
||||||
+ // if their respective sequences of
|
|
||||||
+ // direct subobjects have the same values, and two objects of union type
|
|
||||||
+ // are considered to have the same
|
|
||||||
+ // value if they have the same active member and the corresponding members
|
|
||||||
+ // have the same value.
|
|
||||||
+ // The set of scalar types for which this condition holds is
|
|
||||||
+ // implementation-defined. [ Note: If a type has padding
|
|
||||||
+ // bits, the condition does not hold; otherwise, the condition holds true
|
|
||||||
+ // for unsigned integral types. -- end note ]
|
|
||||||
+ assert(!Ty.isNull() && "Null QualType sent to unique object rep check");
|
|
||||||
+
|
|
||||||
+ // Arrays are unique only if their element type is unique.
|
|
||||||
+ if (Ty->isArrayType())
|
|
||||||
+ return hasUniqueObjectRepresentations(getBaseElementType(Ty));
|
|
||||||
+
|
|
||||||
+ // (9.1) - T is trivially copyable...
|
|
||||||
+ if (!Ty.isTriviallyCopyableType(*this))
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ // All integrals and enums are unique.
|
|
||||||
+ if (Ty->isIntegralOrEnumerationType())
|
|
||||||
+ return true;
|
|
||||||
+
|
|
||||||
+ // All other pointers are unique.
|
|
||||||
+ if (Ty->isPointerType())
|
|
||||||
+ return true;
|
|
||||||
+
|
|
||||||
+ if (Ty->isMemberPointerType()) {
|
|
||||||
+ const MemberPointerType *MPT = Ty->getAs<MemberPointerType>();
|
|
||||||
+ return !ABI->getMemberPointerInfo(MPT).HasPadding;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (Ty->isRecordType()) {
|
|
||||||
+ const RecordDecl *Record = Ty->getAs<RecordType>()->getDecl();
|
|
||||||
+
|
|
||||||
+ if (Record->isInvalidDecl())
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
+ if (Record->isUnion())
|
|
||||||
+ return unionHasUniqueObjectRepresentations(*this, Record);
|
|
||||||
+
|
|
||||||
+ Optional<int64_t> StructSize =
|
|
||||||
+ structHasUniqueObjectRepresentations(*this, Record);
|
|
||||||
+
|
|
||||||
+ return StructSize &&
|
|
||||||
+ StructSize.getValue() == static_cast<int64_t>(getTypeSize(Ty));
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ // FIXME: More cases to handle here (list by rsmith):
|
|
||||||
+ // vectors (careful about, eg, vector of 3 foo)
|
|
||||||
+ // _Complex int and friends
|
|
||||||
+ // _Atomic T
|
|
||||||
+ // Obj-C block pointers
|
|
||||||
+ // Obj-C object pointers
|
|
||||||
+ // and perhaps OpenCL's various builtin types (pipe, sampler_t, event_t,
|
|
||||||
+ // clk_event_t, queue_t, reserve_id_t)
|
|
||||||
+ // There're also Obj-C class types and the Obj-C selector type, but I think it
|
|
||||||
+ // makes sense for those to return false here.
|
|
||||||
+
|
|
||||||
+ return false;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
unsigned ASTContext::CountNonClassIvars(const ObjCInterfaceDecl *OI) const {
|
|
||||||
unsigned count = 0;
|
|
||||||
// Count ivars declared in class extension.
|
|
||||||
diff --git a/tools/clang/lib/AST/CXXABI.h b/tools/clang/lib/AST/CXXABI.h
|
|
||||||
index 924ef00e81..06295b5817 100644
|
|
||||||
--- a/tools/clang/lib/AST/CXXABI.h
|
|
||||||
+++ b/tools/clang/lib/AST/CXXABI.h
|
|
||||||
@@ -31,9 +31,16 @@ class CXXABI {
|
|
||||||
public:
|
|
||||||
virtual ~CXXABI();
|
|
||||||
|
|
||||||
- /// Returns the width and alignment of a member pointer in bits.
|
|
||||||
- virtual std::pair<uint64_t, unsigned>
|
|
||||||
- getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const = 0;
|
|
||||||
+ struct MemberPointerInfo {
|
|
||||||
+ uint64_t Width;
|
|
||||||
+ unsigned Align;
|
|
||||||
+ bool HasPadding;
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ /// Returns the width and alignment of a member pointer in bits, as well as
|
|
||||||
+ /// whether it has padding.
|
|
||||||
+ virtual MemberPointerInfo
|
|
||||||
+ getMemberPointerInfo(const MemberPointerType *MPT) const = 0;
|
|
||||||
|
|
||||||
/// Returns the default calling convention for C++ methods.
|
|
||||||
virtual CallingConv getDefaultMethodCallConv(bool isVariadic) const = 0;
|
|
||||||
diff --git a/tools/clang/lib/AST/ItaniumCXXABI.cpp b/tools/clang/lib/AST/ItaniumCXXABI.cpp
|
|
||||||
index 692a455eaf..d6bc16b635 100644
|
|
||||||
--- a/tools/clang/lib/AST/ItaniumCXXABI.cpp
|
|
||||||
+++ b/tools/clang/lib/AST/ItaniumCXXABI.cpp
|
|
||||||
@@ -101,15 +101,17 @@ protected:
|
|
||||||
public:
|
|
||||||
ItaniumCXXABI(ASTContext &Ctx) : Context(Ctx) { }
|
|
||||||
|
|
||||||
- std::pair<uint64_t, unsigned>
|
|
||||||
- getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const override {
|
|
||||||
+ MemberPointerInfo
|
|
||||||
+ getMemberPointerInfo(const MemberPointerType *MPT) const override {
|
|
||||||
const TargetInfo &Target = Context.getTargetInfo();
|
|
||||||
TargetInfo::IntType PtrDiff = Target.getPtrDiffType(0);
|
|
||||||
- uint64_t Width = Target.getTypeWidth(PtrDiff);
|
|
||||||
- unsigned Align = Target.getTypeAlign(PtrDiff);
|
|
||||||
+ MemberPointerInfo MPI;
|
|
||||||
+ MPI.Width = Target.getTypeWidth(PtrDiff);
|
|
||||||
+ MPI.Align = Target.getTypeAlign(PtrDiff);
|
|
||||||
+ MPI.HasPadding = false;
|
|
||||||
if (MPT->isMemberFunctionPointer())
|
|
||||||
- Width = 2 * Width;
|
|
||||||
- return std::make_pair(Width, Align);
|
|
||||||
+ MPI.Width *= 2;
|
|
||||||
+ return MPI;
|
|
||||||
}
|
|
||||||
|
|
||||||
CallingConv getDefaultMethodCallConv(bool isVariadic) const override {
|
|
||||||
diff --git a/tools/clang/lib/AST/MicrosoftCXXABI.cpp b/tools/clang/lib/AST/MicrosoftCXXABI.cpp
|
|
||||||
index 73324e40f3..b19491f313 100644
|
|
||||||
--- a/tools/clang/lib/AST/MicrosoftCXXABI.cpp
|
|
||||||
+++ b/tools/clang/lib/AST/MicrosoftCXXABI.cpp
|
|
||||||
@@ -76,8 +76,8 @@ class MicrosoftCXXABI : public CXXABI {
|
|
||||||
public:
|
|
||||||
MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { }
|
|
||||||
|
|
||||||
- std::pair<uint64_t, unsigned>
|
|
||||||
- getMemberPointerWidthAndAlign(const MemberPointerType *MPT) const override;
|
|
||||||
+ MemberPointerInfo
|
|
||||||
+ getMemberPointerInfo(const MemberPointerType *MPT) const override;
|
|
||||||
|
|
||||||
CallingConv getDefaultMethodCallConv(bool isVariadic) const override {
|
|
||||||
if (!isVariadic &&
|
|
||||||
@@ -227,7 +227,7 @@ getMSMemberPointerSlots(const MemberPointerType *MPT) {
|
|
||||||
return std::make_pair(Ptrs, Ints);
|
|
||||||
}
|
|
||||||
|
|
||||||
-std::pair<uint64_t, unsigned> MicrosoftCXXABI::getMemberPointerWidthAndAlign(
|
|
||||||
+CXXABI::MemberPointerInfo MicrosoftCXXABI::getMemberPointerInfo(
|
|
||||||
const MemberPointerType *MPT) const {
|
|
||||||
// The nominal struct is laid out with pointers followed by ints and aligned
|
|
||||||
// to a pointer width if any are present and an int width otherwise.
|
|
||||||
@@ -237,22 +237,25 @@ std::pair<uint64_t, unsigned> MicrosoftCXXABI::getMemberPointerWidthAndAlign(
|
|
||||||
|
|
||||||
unsigned Ptrs, Ints;
|
|
||||||
std::tie(Ptrs, Ints) = getMSMemberPointerSlots(MPT);
|
|
||||||
- uint64_t Width = Ptrs * PtrSize + Ints * IntSize;
|
|
||||||
- unsigned Align;
|
|
||||||
+ MemberPointerInfo MPI;
|
|
||||||
+ MPI.HasPadding = false;
|
|
||||||
+ MPI.Width = Ptrs * PtrSize + Ints * IntSize;
|
|
||||||
|
|
||||||
// When MSVC does x86_32 record layout, it aligns aggregate member pointers to
|
|
||||||
// 8 bytes. However, __alignof usually returns 4 for data memptrs and 8 for
|
|
||||||
// function memptrs.
|
|
||||||
if (Ptrs + Ints > 1 && Target.getTriple().isArch32Bit())
|
|
||||||
- Align = 64;
|
|
||||||
+ MPI.Align = 64;
|
|
||||||
else if (Ptrs)
|
|
||||||
- Align = Target.getPointerAlign(0);
|
|
||||||
+ MPI.Align = Target.getPointerAlign(0);
|
|
||||||
else
|
|
||||||
- Align = Target.getIntAlign();
|
|
||||||
+ MPI.Align = Target.getIntAlign();
|
|
||||||
|
|
||||||
- if (Target.getTriple().isArch64Bit())
|
|
||||||
- Width = llvm::alignTo(Width, Align);
|
|
||||||
- return std::make_pair(Width, Align);
|
|
||||||
+ if (Target.getTriple().isArch64Bit()) {
|
|
||||||
+ MPI.Width = llvm::alignTo(MPI.Width, MPI.Align);
|
|
||||||
+ MPI.HasPadding = MPI.Width != (Ptrs * PtrSize + Ints * IntSize);
|
|
||||||
+ }
|
|
||||||
+ return MPI;
|
|
||||||
}
|
|
||||||
|
|
||||||
CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) {
|
|
||||||
diff --git a/tools/clang/lib/Parse/ParseExpr.cpp b/tools/clang/lib/Parse/ParseExpr.cpp
|
|
||||||
index 44b87af01a..73aac10c23 100644
|
|
||||||
--- a/tools/clang/lib/Parse/ParseExpr.cpp
|
|
||||||
+++ b/tools/clang/lib/Parse/ParseExpr.cpp
|
|
||||||
@@ -716,6 +716,7 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
|
|
||||||
/// '__is_sealed' [MS]
|
|
||||||
/// '__is_trivial'
|
|
||||||
/// '__is_union'
|
|
||||||
+/// '__has_unique_object_representations'
|
|
||||||
///
|
|
||||||
/// [Clang] unary-type-trait:
|
|
||||||
/// '__is_aggregate'
|
|
||||||
diff --git a/tools/clang/lib/Sema/SemaExprCXX.cpp b/tools/clang/lib/Sema/SemaExprCXX.cpp
|
|
||||||
index a9cf3ec799..a7d75ad977 100644
|
|
||||||
--- a/tools/clang/lib/Sema/SemaExprCXX.cpp
|
|
||||||
+++ b/tools/clang/lib/Sema/SemaExprCXX.cpp
|
|
||||||
@@ -4141,6 +4141,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
|
|
||||||
case UTT_IsDestructible:
|
|
||||||
case UTT_IsNothrowDestructible:
|
|
||||||
case UTT_IsTriviallyDestructible:
|
|
||||||
+ case UTT_HasUniqueObjectRepresentations:
|
|
||||||
if (ArgTy->isIncompleteArrayType() || ArgTy->isVoidType())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
@@ -4580,6 +4581,8 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
|
|
||||||
// Returns True if and only if T is a complete type at the point of the
|
|
||||||
// function call.
|
|
||||||
return !T->isIncompleteType();
|
|
||||||
+ case UTT_HasUniqueObjectRepresentations:
|
|
||||||
+ return C.hasUniqueObjectRepresentations(T);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/tools/clang/test/SemaCXX/has_unique_object_reps_member_ptr.cpp b/tools/clang/test/SemaCXX/has_unique_object_reps_member_ptr.cpp
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000..b8e27f82ff
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/tools/clang/test/SemaCXX/has_unique_object_reps_member_ptr.cpp
|
|
||||||
@@ -0,0 +1,32 @@
|
|
||||||
+// RUN: %clang_cc1 -triple x86_64-linux-pc -DIS64 -fsyntax-only -verify -std=c++17 %s
|
|
||||||
+// RUN: %clang_cc1 -triple x86_64-windows-pc -DIS64 -fsyntax-only -verify -std=c++17 %s
|
|
||||||
+// RUN: %clang_cc1 -triple i386-linux-pc -fsyntax-only -verify -std=c++17 %s
|
|
||||||
+// RUN: %clang_cc1 -triple i386-windows-pc -DW32 -fsyntax-only -verify -std=c++17 %s
|
|
||||||
+// expected-no-diagnostics
|
|
||||||
+
|
|
||||||
+struct Base {};
|
|
||||||
+struct A : virtual Base {
|
|
||||||
+ virtual void n() {}
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+auto p = &A::n;
|
|
||||||
+static_assert(__has_unique_object_representations(decltype(p)));
|
|
||||||
+
|
|
||||||
+struct B {
|
|
||||||
+ decltype(p) x;
|
|
||||||
+ int b;
|
|
||||||
+#ifdef IS64
|
|
||||||
+ // required on 64 bit to fill out the tail padding.
|
|
||||||
+ int c;
|
|
||||||
+#endif
|
|
||||||
+};
|
|
||||||
+static_assert(__has_unique_object_representations(B));
|
|
||||||
+
|
|
||||||
+struct C { // has padding on Win32, but nothing else.
|
|
||||||
+ decltype(p) x;
|
|
||||||
+};
|
|
||||||
+#ifdef W32
|
|
||||||
+static_assert(!__has_unique_object_representations(C));
|
|
||||||
+#else
|
|
||||||
+static_assert(__has_unique_object_representations(C));
|
|
||||||
+#endif
|
|
||||||
diff --git a/tools/clang/test/SemaCXX/type-traits.cpp b/tools/clang/test/SemaCXX/type-traits.cpp
|
|
||||||
index 5879a77dd5..3c2f9c7f0f 100644
|
|
||||||
--- a/tools/clang/test/SemaCXX/type-traits.cpp
|
|
||||||
+++ b/tools/clang/test/SemaCXX/type-traits.cpp
|
|
||||||
@@ -2352,3 +2352,321 @@ void is_trivially_destructible_test() {
|
|
||||||
{ int arr[F(__is_trivially_destructible(void))]; }
|
|
||||||
{ int arr[F(__is_trivially_destructible(const volatile void))]; }
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+// Instantiation of __has_unique_object_representations
|
|
||||||
+template <typename T>
|
|
||||||
+struct has_unique_object_representations {
|
|
||||||
+ static const bool value = __has_unique_object_representations(T);
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(!has_unique_object_representations<void>::value, "void is never unique");
|
|
||||||
+static_assert(!has_unique_object_representations<const void>::value, "void is never unique");
|
|
||||||
+static_assert(!has_unique_object_representations<volatile void>::value, "void is never unique");
|
|
||||||
+static_assert(!has_unique_object_representations<const volatile void>::value, "void is never unique");
|
|
||||||
+
|
|
||||||
+static_assert(has_unique_object_representations<int>::value, "integrals are");
|
|
||||||
+static_assert(has_unique_object_representations<const int>::value, "integrals are");
|
|
||||||
+static_assert(has_unique_object_representations<volatile int>::value, "integrals are");
|
|
||||||
+static_assert(has_unique_object_representations<const volatile int>::value, "integrals are");
|
|
||||||
+
|
|
||||||
+static_assert(has_unique_object_representations<void *>::value, "as are pointers");
|
|
||||||
+static_assert(has_unique_object_representations<const void *>::value, "as are pointers");
|
|
||||||
+static_assert(has_unique_object_representations<volatile void *>::value, "are pointers");
|
|
||||||
+static_assert(has_unique_object_representations<const volatile void *>::value, "as are pointers");
|
|
||||||
+
|
|
||||||
+static_assert(has_unique_object_representations<int *>::value, "as are pointers");
|
|
||||||
+static_assert(has_unique_object_representations<const int *>::value, "as are pointers");
|
|
||||||
+static_assert(has_unique_object_representations<volatile int *>::value, "as are pointers");
|
|
||||||
+static_assert(has_unique_object_representations<const volatile int *>::value, "as are pointers");
|
|
||||||
+
|
|
||||||
+class C {};
|
|
||||||
+using FP = int (*)(int);
|
|
||||||
+using PMF = int (C::*)(int);
|
|
||||||
+using PMD = int C::*;
|
|
||||||
+
|
|
||||||
+static_assert(has_unique_object_representations<FP>::value, "even function pointers");
|
|
||||||
+static_assert(has_unique_object_representations<const FP>::value, "even function pointers");
|
|
||||||
+static_assert(has_unique_object_representations<volatile FP>::value, "even function pointers");
|
|
||||||
+static_assert(has_unique_object_representations<const volatile FP>::value, "even function pointers");
|
|
||||||
+
|
|
||||||
+static_assert(has_unique_object_representations<PMF>::value, "and pointer to members");
|
|
||||||
+static_assert(has_unique_object_representations<const PMF>::value, "and pointer to members");
|
|
||||||
+static_assert(has_unique_object_representations<volatile PMF>::value, "and pointer to members");
|
|
||||||
+static_assert(has_unique_object_representations<const volatile PMF>::value, "and pointer to members");
|
|
||||||
+
|
|
||||||
+static_assert(has_unique_object_representations<PMD>::value, "and pointer to members");
|
|
||||||
+static_assert(has_unique_object_representations<const PMD>::value, "and pointer to members");
|
|
||||||
+static_assert(has_unique_object_representations<volatile PMD>::value, "and pointer to members");
|
|
||||||
+static_assert(has_unique_object_representations<const volatile PMD>::value, "and pointer to members");
|
|
||||||
+
|
|
||||||
+static_assert(has_unique_object_representations<bool>::value, "yes, all integral types");
|
|
||||||
+static_assert(has_unique_object_representations<char>::value, "yes, all integral types");
|
|
||||||
+static_assert(has_unique_object_representations<signed char>::value, "yes, all integral types");
|
|
||||||
+static_assert(has_unique_object_representations<unsigned char>::value, "yes, all integral types");
|
|
||||||
+static_assert(has_unique_object_representations<short>::value, "yes, all integral types");
|
|
||||||
+static_assert(has_unique_object_representations<unsigned short>::value, "yes, all integral types");
|
|
||||||
+static_assert(has_unique_object_representations<int>::value, "yes, all integral types");
|
|
||||||
+static_assert(has_unique_object_representations<unsigned int>::value, "yes, all integral types");
|
|
||||||
+static_assert(has_unique_object_representations<long>::value, "yes, all integral types");
|
|
||||||
+static_assert(has_unique_object_representations<unsigned long>::value, "yes, all integral types");
|
|
||||||
+static_assert(has_unique_object_representations<long long>::value, "yes, all integral types");
|
|
||||||
+static_assert(has_unique_object_representations<unsigned long long>::value, "yes, all integral types");
|
|
||||||
+static_assert(has_unique_object_representations<wchar_t>::value, "yes, all integral types");
|
|
||||||
+static_assert(has_unique_object_representations<char16_t>::value, "yes, all integral types");
|
|
||||||
+static_assert(has_unique_object_representations<char32_t>::value, "yes, all integral types");
|
|
||||||
+
|
|
||||||
+static_assert(!has_unique_object_representations<void>::value, "but not void!");
|
|
||||||
+static_assert(!has_unique_object_representations<decltype(nullptr)>::value, "or nullptr_t");
|
|
||||||
+static_assert(!has_unique_object_representations<float>::value, "definitely not Floating Point");
|
|
||||||
+static_assert(!has_unique_object_representations<double>::value, "definitely not Floating Point");
|
|
||||||
+static_assert(!has_unique_object_representations<long double>::value, "definitely not Floating Point");
|
|
||||||
+
|
|
||||||
+struct NoPadding {
|
|
||||||
+ int a;
|
|
||||||
+ int b;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(has_unique_object_representations<NoPadding>::value, "types without padding are");
|
|
||||||
+
|
|
||||||
+struct InheritsFromNoPadding : NoPadding {
|
|
||||||
+ int c;
|
|
||||||
+ int d;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(has_unique_object_representations<InheritsFromNoPadding>::value, "types without padding are");
|
|
||||||
+
|
|
||||||
+struct VirtuallyInheritsFromNoPadding : virtual NoPadding {
|
|
||||||
+ int c;
|
|
||||||
+ int d;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(!has_unique_object_representations<VirtuallyInheritsFromNoPadding>::value, "No virtual inheritence");
|
|
||||||
+
|
|
||||||
+struct Padding {
|
|
||||||
+ char a;
|
|
||||||
+ int b;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+//static_assert(!has_unique_object_representations<Padding>::value, "but not with padding");
|
|
||||||
+
|
|
||||||
+struct InheritsFromPadding : Padding {
|
|
||||||
+ int c;
|
|
||||||
+ int d;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(!has_unique_object_representations<InheritsFromPadding>::value, "or its subclasses");
|
|
||||||
+
|
|
||||||
+struct TailPadding {
|
|
||||||
+ int a;
|
|
||||||
+ char b;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(!has_unique_object_representations<TailPadding>::value, "even at the end");
|
|
||||||
+
|
|
||||||
+struct TinyStruct {
|
|
||||||
+ char a;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(has_unique_object_representations<TinyStruct>::value, "Should be no padding");
|
|
||||||
+
|
|
||||||
+struct InheritsFromTinyStruct : TinyStruct {
|
|
||||||
+ int b;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(!has_unique_object_representations<InheritsFromTinyStruct>::value, "Inherit causes padding");
|
|
||||||
+
|
|
||||||
+union NoPaddingUnion {
|
|
||||||
+ int a;
|
|
||||||
+ unsigned int b;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(has_unique_object_representations<NoPaddingUnion>::value, "unions follow the same rules as structs");
|
|
||||||
+
|
|
||||||
+union PaddingUnion {
|
|
||||||
+ int a;
|
|
||||||
+ long long b;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(!has_unique_object_representations<PaddingUnion>::value, "unions follow the same rules as structs");
|
|
||||||
+
|
|
||||||
+struct NotTriviallyCopyable {
|
|
||||||
+ int x;
|
|
||||||
+ NotTriviallyCopyable(const NotTriviallyCopyable &) {}
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(!has_unique_object_representations<NotTriviallyCopyable>::value, "must be trivially copyable");
|
|
||||||
+
|
|
||||||
+struct HasNonUniqueMember {
|
|
||||||
+ float x;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(!has_unique_object_representations<HasNonUniqueMember>::value, "all members must be unique");
|
|
||||||
+
|
|
||||||
+enum ExampleEnum { xExample,
|
|
||||||
+ yExample };
|
|
||||||
+enum LLEnum : long long { xLongExample,
|
|
||||||
+ yLongExample };
|
|
||||||
+
|
|
||||||
+static_assert(has_unique_object_representations<ExampleEnum>::value, "Enums are integrals, so unique!");
|
|
||||||
+static_assert(has_unique_object_representations<LLEnum>::value, "Enums are integrals, so unique!");
|
|
||||||
+
|
|
||||||
+enum class ExampleEnumClass { xExample,
|
|
||||||
+ yExample };
|
|
||||||
+enum class LLEnumClass : long long { xLongExample,
|
|
||||||
+ yLongExample };
|
|
||||||
+
|
|
||||||
+static_assert(has_unique_object_representations<ExampleEnumClass>::value, "Enums are integrals, so unique!");
|
|
||||||
+static_assert(has_unique_object_representations<LLEnumClass>::value, "Enums are integrals, so unique!");
|
|
||||||
+
|
|
||||||
+// because references aren't trivially copyable.
|
|
||||||
+static_assert(!has_unique_object_representations<int &>::value, "No references!");
|
|
||||||
+static_assert(!has_unique_object_representations<const int &>::value, "No references!");
|
|
||||||
+static_assert(!has_unique_object_representations<volatile int &>::value, "No references!");
|
|
||||||
+static_assert(!has_unique_object_representations<const volatile int &>::value, "No references!");
|
|
||||||
+static_assert(!has_unique_object_representations<Empty>::value, "No empty types!");
|
|
||||||
+static_assert(!has_unique_object_representations<EmptyUnion>::value, "No empty types!");
|
|
||||||
+
|
|
||||||
+class Compressed : Empty {
|
|
||||||
+ int x;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(has_unique_object_representations<Compressed>::value, "But inheriting from one is ok");
|
|
||||||
+
|
|
||||||
+class EmptyInheritor : Compressed {};
|
|
||||||
+
|
|
||||||
+static_assert(has_unique_object_representations<EmptyInheritor>::value, "As long as the base has items, empty is ok");
|
|
||||||
+
|
|
||||||
+class Dynamic {
|
|
||||||
+ virtual void A();
|
|
||||||
+ int i;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(!has_unique_object_representations<Dynamic>::value, "Dynamic types are not valid");
|
|
||||||
+
|
|
||||||
+class InheritsDynamic : Dynamic {
|
|
||||||
+ int j;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(!has_unique_object_representations<InheritsDynamic>::value, "Dynamic types are not valid");
|
|
||||||
+
|
|
||||||
+static_assert(has_unique_object_representations<int[42]>::value, "Arrays are fine, as long as their value type is");
|
|
||||||
+static_assert(has_unique_object_representations<int[]>::value, "Arrays are fine, as long as their value type is");
|
|
||||||
+static_assert(has_unique_object_representations<int[][42]>::value, "Arrays are fine, as long as their value type is");
|
|
||||||
+static_assert(!has_unique_object_representations<double[42]>::value, "So no array of doubles!");
|
|
||||||
+static_assert(!has_unique_object_representations<double[]>::value, "So no array of doubles!");
|
|
||||||
+static_assert(!has_unique_object_representations<double[][42]>::value, "So no array of doubles!");
|
|
||||||
+
|
|
||||||
+struct __attribute__((aligned(16))) WeirdAlignment {
|
|
||||||
+ int i;
|
|
||||||
+};
|
|
||||||
+union __attribute__((aligned(16))) WeirdAlignmentUnion {
|
|
||||||
+ int i;
|
|
||||||
+};
|
|
||||||
+static_assert(!has_unique_object_representations<WeirdAlignment>::value, "Alignment causes padding");
|
|
||||||
+static_assert(!has_unique_object_representations<WeirdAlignmentUnion>::value, "Alignment causes padding");
|
|
||||||
+static_assert(!has_unique_object_representations<WeirdAlignment[42]>::value, "Also no arrays that have padding");
|
|
||||||
+
|
|
||||||
+static_assert(!has_unique_object_representations<int(int)>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int) const>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int) volatile>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int) const volatile>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int) &>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int) const &>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int) volatile &>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int) const volatile &>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int) &&>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int) const &&>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int) volatile &&>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int) const volatile &&>::value, "Functions are not unique");
|
|
||||||
+
|
|
||||||
+static_assert(!has_unique_object_representations<int(int, ...)>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int, ...) const>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int, ...) volatile>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int, ...) const volatile>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int, ...) &>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int, ...) const &>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int, ...) volatile &>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int, ...) const volatile &>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int, ...) &&>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int, ...) const &&>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int, ...) volatile &&>::value, "Functions are not unique");
|
|
||||||
+static_assert(!has_unique_object_representations<int(int, ...) const volatile &&>::value, "Functions are not unique");
|
|
||||||
+
|
|
||||||
+void foo(){
|
|
||||||
+ static auto lambda = []() {};
|
|
||||||
+ static_assert(!has_unique_object_representations<decltype(lambda)>::value, "Lambdas follow struct rules");
|
|
||||||
+ int i;
|
|
||||||
+ static auto lambda2 = [i]() {};
|
|
||||||
+ static_assert(has_unique_object_representations<decltype(lambda2)>::value, "Lambdas follow struct rules");
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+struct PaddedBitfield {
|
|
||||||
+ char c : 6;
|
|
||||||
+ char d : 1;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+struct UnPaddedBitfield {
|
|
||||||
+ char c : 6;
|
|
||||||
+ char d : 2;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+struct AlignedPaddedBitfield {
|
|
||||||
+ char c : 6;
|
|
||||||
+ __attribute__((aligned(1)))
|
|
||||||
+ char d : 2;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(!has_unique_object_representations<PaddedBitfield>::value, "Bitfield padding");
|
|
||||||
+static_assert(has_unique_object_representations<UnPaddedBitfield>::value, "Bitfield padding");
|
|
||||||
+static_assert(!has_unique_object_representations<AlignedPaddedBitfield>::value, "Bitfield padding");
|
|
||||||
+
|
|
||||||
+struct BoolBitfield {
|
|
||||||
+ bool b : 8;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(has_unique_object_representations<BoolBitfield>::value, "Bitfield bool");
|
|
||||||
+
|
|
||||||
+struct BoolBitfield2 {
|
|
||||||
+ bool b : 16;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(!has_unique_object_representations<BoolBitfield2>::value, "Bitfield bool");
|
|
||||||
+
|
|
||||||
+struct GreaterSizeBitfield {
|
|
||||||
+ //expected-warning@+1 {{width of bit-field 'n'}}
|
|
||||||
+ int n : 1024;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(sizeof(GreaterSizeBitfield) == 128, "Bitfield Size");
|
|
||||||
+static_assert(!has_unique_object_representations<GreaterSizeBitfield>::value, "Bitfield padding");
|
|
||||||
+
|
|
||||||
+struct StructWithRef {
|
|
||||||
+ int &I;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(has_unique_object_representations<StructWithRef>::value, "References are still unique");
|
|
||||||
+
|
|
||||||
+struct NotUniqueBecauseTailPadding {
|
|
||||||
+ int &r;
|
|
||||||
+ char a;
|
|
||||||
+};
|
|
||||||
+struct CanBeUniqueIfNoPadding : NotUniqueBecauseTailPadding {
|
|
||||||
+ char b[7];
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static_assert(!has_unique_object_representations<NotUniqueBecauseTailPadding>::value,
|
|
||||||
+ "non trivial");
|
|
||||||
+// Can be unique on Itanium, since the is child class' data is 'folded' into the
|
|
||||||
+// parent's tail padding.
|
|
||||||
+static_assert(sizeof(CanBeUniqueIfNoPadding) != 16 ||
|
|
||||||
+ has_unique_object_representations<CanBeUniqueIfNoPadding>::value,
|
|
||||||
+ "inherit from std layout");
|
|
||||||
+
|
|
||||||
+namespace ErrorType {
|
|
||||||
+ struct S; //expected-note{{forward declaration of 'ErrorType::S'}}
|
|
||||||
+
|
|
||||||
+ struct T {
|
|
||||||
+ S t; //expected-error{{field has incomplete type 'ErrorType::S'}}
|
|
||||||
+ };
|
|
||||||
+ bool b = __has_unique_object_representations(T);
|
|
||||||
+};
|
|
||||||
--
|
|
||||||
2.14.1
|
|
||||||
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
diff --git a/tools/clang/include/clang/Basic/TokenKinds.def b/tools/clang/include/clang/Basic/TokenKinds.def
|
|
||||||
index 90ac33b9ea..67fea10788 100644
|
|
||||||
--- a/tools/clang/include/clang/Basic/TokenKinds.def
|
|
||||||
+++ b/tools/clang/include/clang/Basic/TokenKinds.def
|
|
||||||
@@ -390,6 +390,7 @@ TYPE_TRAIT_2(__builtin_types_compatible_p, TypeCompatible, KEYNOCXX)
|
|
||||||
KEYWORD(__builtin_va_arg , KEYALL)
|
|
||||||
KEYWORD(__extension__ , KEYALL)
|
|
||||||
KEYWORD(__float128 , KEYALL)
|
|
||||||
+ALIAS("_Float128", __float128 , KEYNOCXX)
|
|
||||||
KEYWORD(__imag , KEYALL)
|
|
||||||
KEYWORD(__int128 , KEYALL)
|
|
||||||
KEYWORD(__label__ , KEYALL)
|
|
||||||
diff --git a/tools/clang/lib/Frontend/InitPreprocessor.cpp b/tools/clang/lib/Frontend/InitPreprocessor.cpp
|
|
||||||
index 92d61369b4..8edc06fe93 100644
|
|
||||||
--- a/tools/clang/lib/Frontend/InitPreprocessor.cpp
|
|
||||||
+++ b/tools/clang/lib/Frontend/InitPreprocessor.cpp
|
|
||||||
@@ -790,6 +790,10 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
|
|
||||||
DefineFloatMacros(Builder, "FLT", &TI.getFloatFormat(), "F");
|
|
||||||
DefineFloatMacros(Builder, "DBL", &TI.getDoubleFormat(), "");
|
|
||||||
DefineFloatMacros(Builder, "LDBL", &TI.getLongDoubleFormat(), "L");
|
|
||||||
+ if (TI.hasFloat128Type())
|
|
||||||
+ // FIXME: Switch away from the non-standard "Q" when we can
|
|
||||||
+ DefineFloatMacros(Builder, "FLT128", &TI.getFloat128Format(), "Q");
|
|
||||||
+
|
|
||||||
|
|
||||||
// Define a __POINTER_WIDTH__ macro for stdint.h.
|
|
||||||
Builder.defineMacro("__POINTER_WIDTH__",
|
|
||||||
diff --git a/tools/clang/test/Preprocessor/cuda-types.cu b/tools/clang/test/Preprocessor/cuda-types.cu
|
|
||||||
index 5f7b91655c..9e96f6a15e 100644
|
|
||||||
--- a/tools/clang/test/Preprocessor/cuda-types.cu
|
|
||||||
+++ b/tools/clang/test/Preprocessor/cuda-types.cu
|
|
||||||
@@ -5,42 +5,44 @@
|
|
||||||
// FIXME: We really should make __GCC_HAVE_SYNC_COMPARE_AND_SWAP identical on
|
|
||||||
// host and device, but architecturally this is difficult at the moment.
|
|
||||||
|
|
||||||
+// RUN: mkdir -p %t
|
|
||||||
+
|
|
||||||
// RUN: %clang --cuda-host-only -nocudainc -target i386-unknown-linux-gnu -x cuda -E -dM -o - /dev/null \
|
|
||||||
// RUN: | grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)\|define __GCC_ATOMIC' \
|
|
||||||
-// RUN: | grep -v '__LDBL\|_LONG_DOUBLE' > %T/i386-host-defines-filtered
|
|
||||||
+// RUN: | grep -v '__FLT128\|__LDBL\|_LONG_DOUBLE' > %t/i386-host-defines-filtered
|
|
||||||
// RUN: %clang --cuda-device-only -nocudainc -nocudalib -target i386-unknown-linux-gnu -x cuda -E -dM -o - /dev/null \
|
|
||||||
// RUN: | grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)\|define __GCC_ATOMIC' \
|
|
||||||
-// RUN: | grep -v '__LDBL\|_LONG_DOUBLE' > %T/i386-device-defines-filtered
|
|
||||||
-// RUN: diff %T/i386-host-defines-filtered %T/i386-device-defines-filtered
|
|
||||||
+// RUN: | grep -v '__FLT128\|__LDBL\|_LONG_DOUBLE' > %t/i386-device-defines-filtered
|
|
||||||
+// RUN: diff %t/i386-host-defines-filtered %t/i386-device-defines-filtered
|
|
||||||
|
|
||||||
// RUN: %clang --cuda-host-only -nocudainc -target x86_64-unknown-linux-gnu -x cuda -E -dM -o - /dev/null \
|
|
||||||
// RUN: | grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)\|define __GCC_ATOMIC' \
|
|
||||||
-// RUN: | grep -v '__LDBL\|_LONG_DOUBLE' > %T/x86_64-host-defines-filtered
|
|
||||||
+// RUN: | grep -v '__FLT128\|__LDBL\|_LONG_DOUBLE' > %t/x86_64-host-defines-filtered
|
|
||||||
// RUN: %clang --cuda-device-only -nocudainc -nocudalib -target x86_64-unknown-linux-gnu -x cuda -E -dM -o - /dev/null \
|
|
||||||
// RUN: | grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)\|define __GCC_ATOMIC' \
|
|
||||||
-// RUN: | grep -v '__LDBL\|_LONG_DOUBLE' > %T/x86_64-device-defines-filtered
|
|
||||||
-// RUN: diff %T/x86_64-host-defines-filtered %T/x86_64-device-defines-filtered
|
|
||||||
+// RUN: | grep -v '__FLT128\|__LDBL\|_LONG_DOUBLE' > %t/x86_64-device-defines-filtered
|
|
||||||
+// RUN: diff %t/x86_64-host-defines-filtered %t/x86_64-device-defines-filtered
|
|
||||||
|
|
||||||
// RUN: %clang --cuda-host-only -nocudainc -target powerpc64-unknown-linux-gnu -x cuda -E -dM -o - /dev/null \
|
|
||||||
// RUN: | grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)\|define __GCC_ATOMIC' \
|
|
||||||
-// RUN: | grep -v '__LDBL\|_LONG_DOUBLE' > %T/powerpc64-host-defines-filtered
|
|
||||||
+// RUN: | grep -v '__FLT128\|__LDBL\|_LONG_DOUBLE' > %t/powerpc64-host-defines-filtered
|
|
||||||
// RUN: %clang --cuda-device-only -nocudainc -nocudalib -target powerpc64-unknown-linux-gnu -x cuda -E -dM -o - /dev/null \
|
|
||||||
// RUN: | grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)\|define __GCC_ATOMIC' \
|
|
||||||
-// RUN: | grep -v '__LDBL\|_LONG_DOUBLE' > %T/powerpc64-device-defines-filtered
|
|
||||||
-// RUN: diff %T/powerpc64-host-defines-filtered %T/powerpc64-device-defines-filtered
|
|
||||||
+// RUN: | grep -v '__FLT128\|__LDBL\|_LONG_DOUBLE' > %t/powerpc64-device-defines-filtered
|
|
||||||
+// RUN: diff %t/powerpc64-host-defines-filtered %t/powerpc64-device-defines-filtered
|
|
||||||
|
|
||||||
// RUN: %clang --cuda-host-only -nocudainc -target i386-windows-msvc -x cuda -E -dM -o - /dev/null \
|
|
||||||
// RUN: | grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)\|define __GCC_ATOMIC' \
|
|
||||||
-// RUN: | grep -v '__LDBL\|_LONG_DOUBLE' > %T/i386-msvc-host-defines-filtered
|
|
||||||
+// RUN: | grep -v '__FLT128\|__LDBL\|_LONG_DOUBLE' > %t/i386-msvc-host-defines-filtered
|
|
||||||
// RUN: %clang --cuda-device-only -nocudainc -nocudalib -target i386-windows-msvc -x cuda -E -dM -o - /dev/null \
|
|
||||||
// RUN: | grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)\|define __GCC_ATOMIC' \
|
|
||||||
-// RUN: | grep -v '__LDBL\|_LONG_DOUBLE' > %T/i386-msvc-device-defines-filtered
|
|
||||||
-// RUN: diff %T/i386-msvc-host-defines-filtered %T/i386-msvc-device-defines-filtered
|
|
||||||
+// RUN: | grep -v '__FLT128\|__LDBL\|_LONG_DOUBLE' > %t/i386-msvc-device-defines-filtered
|
|
||||||
+// RUN: diff %t/i386-msvc-host-defines-filtered %t/i386-msvc-device-defines-filtered
|
|
||||||
|
|
||||||
// RUN: %clang --cuda-host-only -nocudainc -target x86_64-windows-msvc -x cuda -E -dM -o - /dev/null \
|
|
||||||
// RUN: | grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)\|define __GCC_ATOMIC' \
|
|
||||||
-// RUN: | grep -v '__LDBL\|_LONG_DOUBLE' > %T/x86_64-msvc-host-defines-filtered
|
|
||||||
+// RUN: | grep -v '__FLT128\|__LDBL\|_LONG_DOUBLE' > %t/x86_64-msvc-host-defines-filtered
|
|
||||||
// RUN: %clang --cuda-device-only -nocudainc -nocudalib -target x86_64-windows-msvc -x cuda -E -dM -o - /dev/null \
|
|
||||||
// RUN: | grep 'define __[^ ]*\(TYPE\|MAX\|SIZEOF|WIDTH\)\|define __GCC_ATOMIC' \
|
|
||||||
-// RUN: | grep -v '__LDBL\|_LONG_DOUBLE' > %T/x86_64-msvc-device-defines-filtered
|
|
||||||
-// RUN: diff %T/x86_64-msvc-host-defines-filtered %T/x86_64-msvc-device-defines-filtered
|
|
||||||
+// RUN: | grep -v '__FLT128\|__LDBL\|_LONG_DOUBLE' > %t/x86_64-msvc-device-defines-filtered
|
|
||||||
+// RUN: diff %t/x86_64-msvc-host-defines-filtered %t/x86_64-msvc-device-defines-filtered
|
|
||||||
diff --git a/tools/clang/test/Sema/_Float128.c b/tools/clang/test/Sema/_Float128.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000..f0c3c6d555
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/tools/clang/test/Sema/_Float128.c
|
|
||||||
@@ -0,0 +1,22 @@
|
|
||||||
+// RUN: %clang_cc1 -verify %s
|
|
||||||
+// RUN: %clang_cc1 -triple powerpc64-linux -verify %s
|
|
||||||
+// RUN: %clang_cc1 -triple i686-windows-gnu -verify %s
|
|
||||||
+// RUN: %clang_cc1 -triple x86_64-windows-gnu -verify %s
|
|
||||||
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -verify %s
|
|
||||||
+
|
|
||||||
+#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
|
|
||||||
+_Float128 f;
|
|
||||||
+_Float128 tiny = __FLT128_EPSILON__;
|
|
||||||
+int g(int x, _Float128 *y) {
|
|
||||||
+ return x + *y;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+// expected-no-diagnostics
|
|
||||||
+#else
|
|
||||||
+_Float128 f; // expected-error {{__float128 is not supported on this target}}
|
|
||||||
+float tiny = __FLT128_EPSILON__; // expected-error{{use of undeclared identifier}}
|
|
||||||
+int g(int x, _Float128 *y) { // expected-error {{__float128 is not supported on this target}}
|
|
||||||
+ return x + *y;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#endif // defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
|
|
||||||
--
|
|
||||||
2.14.1
|
|
||||||
|
|
||||||
129
dist/clang/patches/240_Link-clang-tools.patch
vendored
129
dist/clang/patches/240_Link-clang-tools.patch
vendored
@@ -1,129 +0,0 @@
|
|||||||
diff --git a/tools/clang/tools/driver/CMakeLists.txt b/tools/clang/tools/driver/CMakeLists.txt
|
|
||||||
index 901b6d62e4..178e7a1882 100644
|
|
||||||
--- a/tools/clang/tools/driver/CMakeLists.txt
|
|
||||||
+++ b/tools/clang/tools/driver/CMakeLists.txt
|
|
||||||
@@ -43,6 +43,9 @@ target_link_libraries(clang
|
|
||||||
clangDriver
|
|
||||||
clangFrontend
|
|
||||||
clangFrontendTool
|
|
||||||
+ clangTidyPlugin
|
|
||||||
+ clangIncludeFixerPlugin
|
|
||||||
+ clazyPlugin
|
|
||||||
)
|
|
||||||
|
|
||||||
if(WIN32 AND NOT CYGWIN)
|
|
||||||
diff --git a/tools/clang/tools/driver/driver.cpp b/tools/clang/tools/driver/driver.cpp
|
|
||||||
index 9f37c428ff..475c5f84c0 100644
|
|
||||||
--- a/tools/clang/tools/driver/driver.cpp
|
|
||||||
+++ b/tools/clang/tools/driver/driver.cpp
|
|
||||||
@@ -517,3 +517,18 @@ int main(int argc_, const char **argv_) {
|
|
||||||
// failing command.
|
|
||||||
return Res;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+// This anchor is used to force the linker to link the clang-tidy plugin.
|
|
||||||
+extern volatile int ClangTidyPluginAnchorSource;
|
|
||||||
+static int LLVM_ATTRIBUTE_UNUSED ClangTidyPluginAnchorDestination =
|
|
||||||
+ ClangTidyPluginAnchorSource;
|
|
||||||
+
|
|
||||||
+// This anchor is used to force the linker to link the clang-include-fixer
|
|
||||||
+// plugin.
|
|
||||||
+extern volatile int ClangIncludeFixerPluginAnchorSource;
|
|
||||||
+static int LLVM_ATTRIBUTE_UNUSED ClangIncludeFixerPluginAnchorDestination =
|
|
||||||
+ ClangIncludeFixerPluginAnchorSource;
|
|
||||||
+
|
|
||||||
+// This anchor is used to force the linker to link the clazy plugin.
|
|
||||||
+extern volatile int ClazyPluginAnchorSource;
|
|
||||||
+static int LLVM_ATTRIBUTE_UNUSED ClazyPluginAnchorDestination = ClazyPluginAnchorSource;
|
|
||||||
diff --git a/tools/clang/tools/extra/clang-tidy/modernize/LoopConvertCheck.cpp b/tools/clang/tools/extra/clang-tidy/modernize/LoopConvertCheck.cpp
|
|
||||||
index ac0bceb1..305bd78a 100644
|
|
||||||
--- a/tools/clang/tools/extra/clang-tidy/modernize/LoopConvertCheck.cpp
|
|
||||||
+++ b/tools/clang/tools/extra/clang-tidy/modernize/LoopConvertCheck.cpp
|
|
||||||
@@ -44,9 +44,6 @@ static const char EndVarName[] = "endVar";
|
|
||||||
static const char DerefByValueResultName[] = "derefByValueResult";
|
|
||||||
static const char DerefByRefResultName[] = "derefByRefResult";
|
|
||||||
|
|
||||||
-// shared matchers
|
|
||||||
-static const TypeMatcher AnyType = anything();
|
|
||||||
-
|
|
||||||
static const StatementMatcher IntegerComparisonMatcher =
|
|
||||||
expr(ignoringParenImpCasts(
|
|
||||||
declRefExpr(to(varDecl(hasType(isInteger())).bind(ConditionVarName)))));
|
|
||||||
@@ -173,6 +170,8 @@ StatementMatcher makeIteratorLoopMatcher() {
|
|
||||||
qualType(unless(hasCanonicalType(rValueReferenceType())))
|
|
||||||
.bind(DerefByRefResultName)))))));
|
|
||||||
|
|
||||||
+ static const TypeMatcher AnyType = anything();
|
|
||||||
+
|
|
||||||
return forStmt(
|
|
||||||
unless(isInTemplateInstantiation()),
|
|
||||||
hasLoopInit(anyOf(declStmt(declCountIs(2),
|
|
||||||
diff --git a/tools/clang/tools/extra/clang-tidy/plugin/CMakeLists.txt b/tools/clang/tools/extra/clang-tidy/plugin/CMakeLists.txt
|
|
||||||
index 5c888327..832e2090 100644
|
|
||||||
--- a/tools/clang/tools/extra/clang-tidy/plugin/CMakeLists.txt
|
|
||||||
+++ b/tools/clang/tools/extra/clang-tidy/plugin/CMakeLists.txt
|
|
||||||
@@ -10,9 +10,11 @@ add_clang_library(clangTidyPlugin
|
|
||||||
clangTidy
|
|
||||||
clangTidyAndroidModule
|
|
||||||
clangTidyBoostModule
|
|
||||||
+ clangTidyBugproneModule
|
|
||||||
clangTidyCERTModule
|
|
||||||
clangTidyCppCoreGuidelinesModule
|
|
||||||
clangTidyGoogleModule
|
|
||||||
+ clangTidyHICPPModule
|
|
||||||
clangTidyLLVMModule
|
|
||||||
clangTidyMiscModule
|
|
||||||
clangTidyModernizeModule
|
|
||||||
diff --git a/tools/clang/tools/extra/clang-tidy/plugin/ClangTidyPlugin.cpp b/tools/clang/tools/extra/clang-tidy/plugin/ClangTidyPlugin.cpp
|
|
||||||
index 1e6346c2..7028c40c 100644
|
|
||||||
--- a/tools/clang/tools/extra/clang-tidy/plugin/ClangTidyPlugin.cpp
|
|
||||||
+++ b/tools/clang/tools/extra/clang-tidy/plugin/ClangTidyPlugin.cpp
|
|
||||||
@@ -83,6 +83,16 @@ extern volatile int CERTModuleAnchorSource;
|
|
||||||
static int LLVM_ATTRIBUTE_UNUSED CERTModuleAnchorDestination =
|
|
||||||
CERTModuleAnchorSource;
|
|
||||||
|
|
||||||
+// This anchor is used to force the linker to link the BoostModule.
|
|
||||||
+extern volatile int BoostModuleAnchorSource;
|
|
||||||
+static int LLVM_ATTRIBUTE_UNUSED BoostModuleAnchorDestination =
|
|
||||||
+ BoostModuleAnchorSource;
|
|
||||||
+
|
|
||||||
+// This anchor is used to force the linker to link the BugproneModule.
|
|
||||||
+extern volatile int BugproneModuleAnchorSource;
|
|
||||||
+static int LLVM_ATTRIBUTE_UNUSED BugproneModuleAnchorDestination =
|
|
||||||
+ BugproneModuleAnchorSource;
|
|
||||||
+
|
|
||||||
// This anchor is used to force the linker to link the LLVMModule.
|
|
||||||
extern volatile int LLVMModuleAnchorSource;
|
|
||||||
static int LLVM_ATTRIBUTE_UNUSED LLVMModuleAnchorDestination =
|
|
||||||
@@ -98,6 +108,11 @@ extern volatile int GoogleModuleAnchorSource;
|
|
||||||
static int LLVM_ATTRIBUTE_UNUSED GoogleModuleAnchorDestination =
|
|
||||||
GoogleModuleAnchorSource;
|
|
||||||
|
|
||||||
+// This anchor is used to force the linker to link the AndroidModule.
|
|
||||||
+extern volatile int AndroidModuleAnchorSource;
|
|
||||||
+static int LLVM_ATTRIBUTE_UNUSED AndroidModuleAnchorDestination =
|
|
||||||
+ AndroidModuleAnchorSource;
|
|
||||||
+
|
|
||||||
// This anchor is used to force the linker to link the MiscModule.
|
|
||||||
extern volatile int MiscModuleAnchorSource;
|
|
||||||
static int LLVM_ATTRIBUTE_UNUSED MiscModuleAnchorDestination =
|
|
||||||
@@ -111,7 +126,7 @@ static int LLVM_ATTRIBUTE_UNUSED ModernizeModuleAnchorDestination =
|
|
||||||
// This anchor is used to force the linker to link the MPIModule.
|
|
||||||
extern volatile int MPIModuleAnchorSource;
|
|
||||||
static int LLVM_ATTRIBUTE_UNUSED MPIModuleAnchorDestination =
|
|
||||||
- MPIModuleAnchorSource;
|
|
||||||
+ MPIModuleAnchorSource;
|
|
||||||
|
|
||||||
// This anchor is used to force the linker to link the PerformanceModule.
|
|
||||||
extern volatile int PerformanceModuleAnchorSource;
|
|
||||||
@@ -123,5 +138,10 @@ extern volatile int ReadabilityModuleAnchorSource;
|
|
||||||
static int LLVM_ATTRIBUTE_UNUSED ReadabilityModuleAnchorDestination =
|
|
||||||
ReadabilityModuleAnchorSource;
|
|
||||||
|
|
||||||
+// This anchor is used to force the linker to link the HICPPModule.
|
|
||||||
+extern volatile int HICPPModuleAnchorSource;
|
|
||||||
+static int LLVM_ATTRIBUTE_UNUSED HICPPModuleAnchorDestination =
|
|
||||||
+ HICPPModuleAnchorSource;
|
|
||||||
+
|
|
||||||
} // namespace tidy
|
|
||||||
} // namespace clang
|
|
||||||
149
dist/clang/patches/README.md
vendored
149
dist/clang/patches/README.md
vendored
@@ -1,149 +0,0 @@
|
|||||||
Extra patches to LLVM/Clang 5.0
|
|
||||||
===============================
|
|
||||||
|
|
||||||
The patches in this directory are applied to LLVM/Clang with:
|
|
||||||
|
|
||||||
$ cd $LLVM_SOURCE_DIR
|
|
||||||
$ git apply --whitespace=fix $QT_CREATOR_SOURCE/dist/clang/patches/*.patch
|
|
||||||
|
|
||||||
Backported changes
|
|
||||||
------------------
|
|
||||||
|
|
||||||
##### 110_D41016_Fix-crash-in-unused-lambda-capture-warning-for-VLAs.patch
|
|
||||||
|
|
||||||
* <https://reviews.llvm.org/D41016>
|
|
||||||
|
|
||||||
[Sema] Fix crash in unused-lambda-capture warning for VLAs
|
|
||||||
|
|
||||||
##### 010_D35355_Fix-templated-type-alias-completion-when-using-global-completion-cache.patch
|
|
||||||
|
|
||||||
* <https://reviews.llvm.org/D35355>
|
|
||||||
|
|
||||||
Fixes completion involving templated type alias.
|
|
||||||
|
|
||||||
##### 120_D41688_Fix-crash-on-code-completion-in-comment-in-included-file.patch
|
|
||||||
|
|
||||||
* <https://reviews.llvm.org/D41688>
|
|
||||||
|
|
||||||
[Lex] Fix crash on code completion in comment in included file.
|
|
||||||
|
|
||||||
##### 100_D40841_Fix-a-crash-on-C++17-AST-for-non-trivial-construction-into-a-trivial-brace-initialize.patch
|
|
||||||
|
|
||||||
* <https://reviews.llvm.org/D40841>
|
|
||||||
|
|
||||||
[analyzer] Fix a crash on C++17 AST for non-trivial construction into a trivial brace initializer.
|
|
||||||
|
|
||||||
##### 090_D40746_Correctly-handle-line-table-entries-without-filenames-during-AST-serialization.patch
|
|
||||||
|
|
||||||
* <https://reviews.llvm.org/D40746>
|
|
||||||
|
|
||||||
Correctly handle line table entries without filenames during AST serialization
|
|
||||||
Fixes crash during a reparse.
|
|
||||||
|
|
||||||
##### 050_D40027_Fix-cursors-for-in-class-initializer-of-field-declarations.patch
|
|
||||||
|
|
||||||
* <https://reviews.llvm.org/D40027>
|
|
||||||
* <https://bugs.llvm.org/show_bug.cgi?id=33745>
|
|
||||||
|
|
||||||
[libclang] Fix cursors for in-class initializer of field declarations
|
|
||||||
Fixes AST access to initializers of class members. Affects mostly semantic highlighting and highlighting of local uses.
|
|
||||||
|
|
||||||
##### 070_D40561_Fix-cursors-for-functions-with-trailing-return-type.patch
|
|
||||||
|
|
||||||
* <https://reviews.llvm.org/D40561>
|
|
||||||
|
|
||||||
[libclang] Fix cursors for functions with trailing return type
|
|
||||||
|
|
||||||
##### 060_D40072_Support-querying-whether-a-declaration-is-invalid.patch
|
|
||||||
|
|
||||||
* <https://reviews.llvm.org/D40072>
|
|
||||||
|
|
||||||
[libclang] Add support for checking abstractness of records
|
|
||||||
Would need https://codereview.qt-project.org/#/c/211497/ on Qt Creator side.
|
|
||||||
|
|
||||||
##### 040_D39957_Honor-TerseOutput-for-constructors.patch
|
|
||||||
|
|
||||||
* <https://reviews.llvm.org/D39957>
|
|
||||||
|
|
||||||
[DeclPrinter] Honor TerseOutput for constructors
|
|
||||||
Avoids printing member initialization list and body for constructor.
|
|
||||||
|
|
||||||
##### 080_D40643_Add-function-to-get-the-buffer-for-a-file.patch
|
|
||||||
|
|
||||||
* <https://reviews.llvm.org/D40643>
|
|
||||||
* <https://reviews.llvm.org/rL319881>
|
|
||||||
|
|
||||||
[libclang] Add function to get the buffer for a file
|
|
||||||
Together with https://codereview.qt-project.org/#/c/212972/ fixes highlighting
|
|
||||||
|
|
||||||
##### 030_D38615_Only-mark-CXCursors-for-explicit-attributes-with-a-type.patch
|
|
||||||
|
|
||||||
* <https://reviews.llvm.org/D38615>
|
|
||||||
|
|
||||||
[libclang] Only mark CXCursors for explicit attributes with a type
|
|
||||||
Some classes have totally broken highlighting (like classes inside texteditor.cpp)
|
|
||||||
|
|
||||||
##### 170_D40013_DeclPrinter-Allow-printing-fully-qualified-name.patch
|
|
||||||
##### 180_D39903_libclang-Allow-pretty-printing-declarations.patch
|
|
||||||
|
|
||||||
* <https://reviews.llvm.org/D40013>
|
|
||||||
* <https://reviews.llvm.org/D39903>
|
|
||||||
|
|
||||||
[DeclPrinter] Allow printing fully qualified name of function declaration
|
|
||||||
[libclang] Allow pretty printing declarations
|
|
||||||
|
|
||||||
Improves pretty printing for tooltips.
|
|
||||||
|
|
||||||
##### 220_Support-std-has_unique_object_represesentations.patch
|
|
||||||
|
|
||||||
* https://reviews.llvm.org/D39064 mplement __has_unique_object_representations
|
|
||||||
* https://reviews.llvm.org/D39347 Fix __has_unique_object_representations implementation
|
|
||||||
* (without review, git sha1 133cba2f9263f63f44b6b086a500f374bff13eee) Fix ICE when __has_unqiue_object_representations called with invalid decl
|
|
||||||
* (without review, git cb61fc53dc997bca3bee98d898d3406d0acb221c) Revert unintended hunk from ICE-Change
|
|
||||||
* https://reviews.llvm.org/D42863 Make __has_unique_object_representations reject empty union types.
|
|
||||||
|
|
||||||
Backport patches implementing std::has_unique_object_representations for
|
|
||||||
parsing type_traits header of stdlibc++ 7.
|
|
||||||
|
|
||||||
|
|
||||||
##### 230_D40673_Add-Float128-as-alias-to-__float128.patch
|
|
||||||
|
|
||||||
* https://reviews.llvm.org/D40673
|
|
||||||
|
|
||||||
Fixes parsing stdlib.h with -DGNU_SOURCE for GCC 7.2 (and maybe others).
|
|
||||||
|
|
||||||
Additional changes
|
|
||||||
------------------
|
|
||||||
|
|
||||||
##### 160_QTCREATORBUG-15449_Fix-files-lock-on-Windows.patch
|
|
||||||
|
|
||||||
* <https://reviews.llvm.org/D35200>
|
|
||||||
* <https://bugreports.qt.io/browse/QTCREATORBUG-15449>
|
|
||||||
|
|
||||||
Significantly reduces problems when saving a header file on Windows.
|
|
||||||
|
|
||||||
##### 150_QTCREATORBUG-15157_Link-with-clazy_llvm.patch
|
|
||||||
##### 130_QTCREATORBUG-15157_Link-with-clazy_clang.patch
|
|
||||||
##### 140_QTCREATORBUG-15157_Link-with-clazy_extra.patch
|
|
||||||
|
|
||||||
* <https://bugreports.qt.io/browse/QTCREATORBUG-15157>
|
|
||||||
|
|
||||||
Builds Clazy as an LLVM part and forces link for Clazy plugin registry entry.
|
|
||||||
|
|
||||||
##### 200_D36390_Fix-overloaded-static-functions-in-SemaCodeComplete.patch
|
|
||||||
|
|
||||||
* <https://reviews.llvm.org/D36390>
|
|
||||||
* <https://bugs.llvm.org/show_bug.cgi?id=33904>
|
|
||||||
|
|
||||||
Fix overloaded static functions in SemaCodeComplete
|
|
||||||
|
|
||||||
Happens when static function is accessed via the class variable.
|
|
||||||
That leads to incorrect overloads number because the variable is considered as the first argument.
|
|
||||||
|
|
||||||
##### 210_D43453_Fix-overloaded-static-functions-for-templates.patch
|
|
||||||
|
|
||||||
* <https://reviews.llvm.org/D43453>
|
|
||||||
|
|
||||||
Fix overloaded static functions for templates
|
|
||||||
|
|
||||||
Apply almost the same fix as D36390 but for templates
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
var Environment = require("qbs.Environment")
|
var Environment = require("qbs.Environment")
|
||||||
var File = require("qbs.File")
|
var File = require("qbs.File")
|
||||||
var FileInfo = require("qbs.FileInfo")
|
var FileInfo = require("qbs.FileInfo")
|
||||||
var MinimumLLVMVersion = "5.0.0" // CLANG-UPGRADE-CHECK: Adapt minimum version numbers.
|
var MinimumLLVMVersion = "6.0.0" // CLANG-UPGRADE-CHECK: Adapt minimum version numbers.
|
||||||
var Process = require("qbs.Process")
|
var Process = require("qbs.Process")
|
||||||
|
|
||||||
function readOutput(executable, args)
|
function readOutput(executable, args)
|
||||||
@@ -36,7 +36,7 @@ function llvmConfig(hostOS, qtcFunctions)
|
|||||||
{
|
{
|
||||||
var llvmInstallDirFromEnv = Environment.getEnv("LLVM_INSTALL_DIR")
|
var llvmInstallDirFromEnv = Environment.getEnv("LLVM_INSTALL_DIR")
|
||||||
var llvmConfigVariants = [
|
var llvmConfigVariants = [
|
||||||
"llvm-config", "llvm-config-5.0", "llvm-config-6.0", "llvm-config-7.0", "llvm-config-8.0",
|
"llvm-config", "llvm-config-6.0", "llvm-config-7.0", "llvm-config-8.0", "llvm-config-9.0"
|
||||||
];
|
];
|
||||||
|
|
||||||
// Prefer llvm-config* from LLVM_INSTALL_DIR
|
// Prefer llvm-config* from LLVM_INSTALL_DIR
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ Module {
|
|||||||
})
|
})
|
||||||
property stringList llvmToolingCxxFlags: clangProbe.llvmToolingCxxFlags
|
property stringList llvmToolingCxxFlags: clangProbe.llvmToolingCxxFlags
|
||||||
property bool toolingEnabled: !Environment.getEnv("QTC_NO_CLANG_LIBTOOLING")
|
property bool toolingEnabled: !Environment.getEnv("QTC_NO_CLANG_LIBTOOLING")
|
||||||
&& Utilities.versionCompare(llvmVersion, "5") > 0
|
&& Utilities.versionCompare(llvmVersion, "6") > 0
|
||||||
&& Utilities.versionCompare(llvmVersion, "6") < 0
|
&& Utilities.versionCompare(llvmVersion, "7") < 0
|
||||||
|
|
||||||
validate: {
|
validate: {
|
||||||
if (!clangProbe.found) {
|
if (!clangProbe.found) {
|
||||||
|
|||||||
@@ -101,10 +101,10 @@ isEmpty(LLVM_VERSION) {
|
|||||||
$$llvmWarningOrError(\
|
$$llvmWarningOrError(\
|
||||||
"Cannot determine clang version. Set LLVM_INSTALL_DIR to build the Clang Code Model",\
|
"Cannot determine clang version. Set LLVM_INSTALL_DIR to build the Clang Code Model",\
|
||||||
"LLVM_INSTALL_DIR does not contain a valid llvm-config, candidate: $$llvm_config")
|
"LLVM_INSTALL_DIR does not contain a valid llvm-config, candidate: $$llvm_config")
|
||||||
} else:!versionIsAtLeast($$LLVM_VERSION, 5, 0, 0): {
|
} else:!versionIsAtLeast($$LLVM_VERSION, 6, 0, 0): {
|
||||||
# CLANG-UPGRADE-CHECK: Adapt minimum version numbers.
|
# CLANG-UPGRADE-CHECK: Adapt minimum version numbers.
|
||||||
$$llvmWarningOrError(\
|
$$llvmWarningOrError(\
|
||||||
"LLVM/Clang version >= 5.0.0 required, version provided: $$LLVM_VERSION")
|
"LLVM/Clang version >= 6.0.0 required, version provided: $$LLVM_VERSION")
|
||||||
LLVM_VERSION =
|
LLVM_VERSION =
|
||||||
} else {
|
} else {
|
||||||
LLVM_LIBDIR = $$quote($$system($$llvm_config --libdir, lines))
|
LLVM_LIBDIR = $$quote($$system($$llvm_config --libdir, lines))
|
||||||
@@ -141,11 +141,11 @@ isEmpty(LLVM_VERSION) {
|
|||||||
QTC_NO_CLANG_LIBTOOLING=$$(QTC_NO_CLANG_LIBTOOLING)
|
QTC_NO_CLANG_LIBTOOLING=$$(QTC_NO_CLANG_LIBTOOLING)
|
||||||
isEmpty(QTC_NO_CLANG_LIBTOOLING) {
|
isEmpty(QTC_NO_CLANG_LIBTOOLING) {
|
||||||
QTC_FORCE_CLANG_LIBTOOLING = $$(QTC_FORCE_CLANG_LIBTOOLING)
|
QTC_FORCE_CLANG_LIBTOOLING = $$(QTC_FORCE_CLANG_LIBTOOLING)
|
||||||
versionIsEqual($$LLVM_VERSION, 5, 0)|!isEmpty(QTC_FORCE_CLANG_LIBTOOLING) {
|
versionIsEqual($$LLVM_VERSION, 6, 0)|!isEmpty(QTC_FORCE_CLANG_LIBTOOLING) {
|
||||||
!contains(QMAKE_DEFAULT_LIBDIRS, $$LLVM_LIBDIR): LIBTOOLING_LIBS = -L$${LLVM_LIBDIR}
|
!contains(QMAKE_DEFAULT_LIBDIRS, $$LLVM_LIBDIR): LIBTOOLING_LIBS = -L$${LLVM_LIBDIR}
|
||||||
LIBTOOLING_LIBS += $$CLANGTOOLING_LIBS $$LLVM_STATIC_LIBS
|
LIBTOOLING_LIBS += $$CLANGTOOLING_LIBS $$LLVM_STATIC_LIBS
|
||||||
} else {
|
} else {
|
||||||
warning("Clang LibTooling is disabled because only version 5.0 is supported.")
|
warning("Clang LibTooling is disabled because only version 6.0 is supported.")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
warning("Clang LibTooling is disabled.")
|
warning("Clang LibTooling is disabled.")
|
||||||
|
|||||||
@@ -163,8 +163,7 @@ static const char *builtinTypeToText(CXTypeKind kind)
|
|||||||
|
|
||||||
// https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html
|
// https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html
|
||||||
case CXType_Float128: return "__float128";
|
case CXType_Float128: return "__float128";
|
||||||
// CLANG-UPGRADE-CHECK: CXType_Float16 available with >= clang-6.0:
|
case CXType_Float16: return "_Float16";
|
||||||
// case CXType_Float16: return "_Float16";
|
|
||||||
|
|
||||||
// https://www.khronos.org/registry/OpenCL/sdk/2.1/docs/man/xhtml/scalarDataTypes.html
|
// https://www.khronos.org/registry/OpenCL/sdk/2.1/docs/man/xhtml/scalarDataTypes.html
|
||||||
case CXType_Half:
|
case CXType_Half:
|
||||||
|
|||||||
@@ -93,8 +93,6 @@ SourceLocation::SourceLocation(CXTranslationUnit cxTranslationUnit,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
filePath_ = ClangString(clang_getFileName(cxFile));
|
filePath_ = ClangString(clang_getFileName(cxFile));
|
||||||
// CLANG-UPGRADE-CHECK: Remove HAS_GETFILECONTENTS_BACKPORTED check once we require clang >= 7.0
|
|
||||||
#if defined(CINDEX_VERSION_HAS_GETFILECONTENTS_BACKPORTED) || CINDEX_VERSION_MINOR >= 47
|
|
||||||
if (column_ > 1) {
|
if (column_ > 1) {
|
||||||
const uint lineStart = offset_ + 1 - column_;
|
const uint lineStart = offset_ + 1 - column_;
|
||||||
const char *contents = clang_getFileContents(cxTranslationUnit, cxFile, nullptr);
|
const char *contents = clang_getFileContents(cxTranslationUnit, cxFile, nullptr);
|
||||||
@@ -106,7 +104,6 @@ SourceLocation::SourceLocation(CXTranslationUnit cxTranslationUnit,
|
|||||||
column_ = static_cast<uint>(QString::fromUtf8(&contents[lineStart],
|
column_ = static_cast<uint>(QString::fromUtf8(&contents[lineStart],
|
||||||
static_cast<int>(column_)).size());
|
static_cast<int>(column_)).size());
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceLocation::SourceLocation(CXTranslationUnit cxTranslationUnit,
|
SourceLocation::SourceLocation(CXTranslationUnit cxTranslationUnit,
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ include($$PWD/../../../src/shared/clang/clang_defines.pri)
|
|||||||
include($$PWD/../../../src/tools/clangbackend/source/clangbackendclangipc-source.pri)
|
include($$PWD/../../../src/tools/clangbackend/source/clangbackendclangipc-source.pri)
|
||||||
include($$PWD/../../../src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri)
|
include($$PWD/../../../src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri)
|
||||||
} else {
|
} else {
|
||||||
DEFINES += CLANG_VERSION=\\\"5.0.0\\\"
|
DEFINES += CLANG_VERSION=\\\"6.0.0\\\"
|
||||||
DEFINES += "\"CLANG_RESOURCE_DIR=\\\"/usr/include\\\"\""
|
DEFINES += "\"CLANG_RESOURCE_DIR=\\\"/usr/include\\\"\""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ TEST_F(SkippedSourceRanges, DISABLED_ON_WINDOWS(RangeOne))
|
|||||||
{
|
{
|
||||||
auto ranges = skippedSourceRanges.sourceRanges();
|
auto ranges = skippedSourceRanges.sourceRanges();
|
||||||
|
|
||||||
ASSERT_THAT(ranges[0].start(), IsSourceLocation(filePath, 1, 2, 1));
|
ASSERT_THAT(ranges[0].start(), IsSourceLocation(filePath, 1, 1, 0));
|
||||||
ASSERT_THAT(ranges[0].end(), IsSourceLocation(filePath, 5, 1, 18));
|
ASSERT_THAT(ranges[0].end(), IsSourceLocation(filePath, 5, 1, 18));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +156,7 @@ TEST_F(SkippedSourceRanges, DISABLED_ON_WINDOWS(RangeTwo))
|
|||||||
{
|
{
|
||||||
auto ranges = skippedSourceRanges.sourceRanges();
|
auto ranges = skippedSourceRanges.sourceRanges();
|
||||||
|
|
||||||
ASSERT_THAT(ranges[1].start(), IsSourceLocation(filePath, 7, 2, 27));
|
ASSERT_THAT(ranges[1].start(), IsSourceLocation(filePath, 7, 1, 26));
|
||||||
ASSERT_THAT(ranges[1].end(), IsSourceLocation(filePath, 12, 1, 57));
|
ASSERT_THAT(ranges[1].end(), IsSourceLocation(filePath, 12, 1, 57));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user