forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/4.7'
Change-Id: I00dd929a4ed32af8f1b76cea57a7c49239dafc7c
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 https://code.qt.io/clang/llvm
|
||||||
|
|
||||||
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 https://code.qt.io/clang/clang 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) {
|
||||||
|
@@ -65,7 +65,7 @@ Controls.TextField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ExtendedFunctionButton {
|
ExtendedFunctionButton {
|
||||||
x: 2
|
x: 4
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
backendValue: lineEdit.backendValue
|
backendValue: lineEdit.backendValue
|
||||||
visible: lineEdit.enabled && showExtendedFunctionButton
|
visible: lineEdit.enabled && showExtendedFunctionButton
|
||||||
@@ -127,7 +127,7 @@ Controls.TextField {
|
|||||||
|
|
||||||
padding.top: 2
|
padding.top: 2
|
||||||
padding.bottom: 2
|
padding.bottom: 2
|
||||||
padding.left: 16
|
padding.left: 18
|
||||||
padding.right: lineEdit.showTranslateCheckBox ? 16 : 1
|
padding.right: lineEdit.showTranslateCheckBox ? 16 : 1
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
implicitWidth: 100
|
implicitWidth: 100
|
||||||
|
@@ -33,8 +33,10 @@ Controls.SpinBox {
|
|||||||
property color textColor: colorLogic.textColor
|
property color textColor: colorLogic.textColor
|
||||||
property variant backendValue;
|
property variant backendValue;
|
||||||
|
|
||||||
|
implicitWidth: 74
|
||||||
|
|
||||||
ExtendedFunctionButton {
|
ExtendedFunctionButton {
|
||||||
x: 2
|
x: 4
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
backendValue: spinBox.backendValue
|
backendValue: spinBox.backendValue
|
||||||
visible: spinBox.enabled
|
visible: spinBox.enabled
|
||||||
@@ -59,4 +61,5 @@ Controls.SpinBox {
|
|||||||
|
|
||||||
style: CustomSpinBoxStyle {
|
style: CustomSpinBoxStyle {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -191,8 +191,8 @@ TextEditor_CurrentLine_ScrollBarColor=ffffffff
|
|||||||
ProjectExplorer_TaskError_TextMarkColor=error
|
ProjectExplorer_TaskError_TextMarkColor=error
|
||||||
ProjectExplorer_TaskWarn_TextMarkColor=warning
|
ProjectExplorer_TaskWarn_TextMarkColor=warning
|
||||||
|
|
||||||
ClangCodeModel_Error_TextMarkColor=error
|
CodeModel_Error_TextMarkColor=error
|
||||||
ClangCodeModel_Warning_TextMarkColor=warning
|
CodeModel_Warning_TextMarkColor=warning
|
||||||
|
|
||||||
PaletteWindow=normalBackground
|
PaletteWindow=normalBackground
|
||||||
PaletteWindowText=text
|
PaletteWindowText=text
|
||||||
|
@@ -184,8 +184,8 @@ TextEditor_CurrentLine_ScrollBarColor=ff404040
|
|||||||
ProjectExplorer_TaskError_TextMarkColor=error
|
ProjectExplorer_TaskError_TextMarkColor=error
|
||||||
ProjectExplorer_TaskWarn_TextMarkColor=warning
|
ProjectExplorer_TaskWarn_TextMarkColor=warning
|
||||||
|
|
||||||
ClangCodeModel_Error_TextMarkColor=error
|
CodeModel_Error_TextMarkColor=error
|
||||||
ClangCodeModel_Warning_TextMarkColor=warning
|
CodeModel_Warning_TextMarkColor=warning
|
||||||
|
|
||||||
QmlDesigner_BackgroundColor=qmlDesignerButtonColor
|
QmlDesigner_BackgroundColor=qmlDesignerButtonColor
|
||||||
QmlDesigner_HighlightColor=ff46a2da
|
QmlDesigner_HighlightColor=ff46a2da
|
||||||
|
@@ -195,8 +195,8 @@ TextEditor_CurrentLine_ScrollBarColor=ffffffff
|
|||||||
ProjectExplorer_TaskError_TextMarkColor=error
|
ProjectExplorer_TaskError_TextMarkColor=error
|
||||||
ProjectExplorer_TaskWarn_TextMarkColor=warning
|
ProjectExplorer_TaskWarn_TextMarkColor=warning
|
||||||
|
|
||||||
ClangCodeModel_Error_TextMarkColor=error
|
CodeModel_Error_TextMarkColor=error
|
||||||
ClangCodeModel_Warning_TextMarkColor=warning
|
CodeModel_Warning_TextMarkColor=warning
|
||||||
|
|
||||||
QmlDesigner_BackgroundColor=qmlDesignerButtonColor
|
QmlDesigner_BackgroundColor=qmlDesignerButtonColor
|
||||||
QmlDesigner_HighlightColor=ff3f91c4
|
QmlDesigner_HighlightColor=ff3f91c4
|
||||||
|
@@ -193,8 +193,8 @@ TextEditor_CurrentLine_ScrollBarColor=ff404040
|
|||||||
ProjectExplorer_TaskError_TextMarkColor=error
|
ProjectExplorer_TaskError_TextMarkColor=error
|
||||||
ProjectExplorer_TaskWarn_TextMarkColor=warning
|
ProjectExplorer_TaskWarn_TextMarkColor=warning
|
||||||
|
|
||||||
ClangCodeModel_Error_TextMarkColor=error
|
CodeModel_Error_TextMarkColor=error
|
||||||
ClangCodeModel_Warning_TextMarkColor=warning
|
CodeModel_Warning_TextMarkColor=warning
|
||||||
|
|
||||||
QmlDesigner_BackgroundColor=qmlDesignerButtonColor
|
QmlDesigner_BackgroundColor=qmlDesignerButtonColor
|
||||||
QmlDesigner_HighlightColor=ff46a2da
|
QmlDesigner_HighlightColor=ff46a2da
|
||||||
|
@@ -191,8 +191,8 @@ TextEditor_CurrentLine_ScrollBarColor=ff404040
|
|||||||
ProjectExplorer_TaskError_TextMarkColor=error
|
ProjectExplorer_TaskError_TextMarkColor=error
|
||||||
ProjectExplorer_TaskWarn_TextMarkColor=warning
|
ProjectExplorer_TaskWarn_TextMarkColor=warning
|
||||||
|
|
||||||
ClangCodeModel_Error_TextMarkColor=error
|
CodeModel_Error_TextMarkColor=error
|
||||||
ClangCodeModel_Warning_TextMarkColor=warning
|
CodeModel_Warning_TextMarkColor=warning
|
||||||
|
|
||||||
QmlDesigner_BackgroundColor=qmlDesignerButtonColor
|
QmlDesigner_BackgroundColor=qmlDesignerButtonColor
|
||||||
QmlDesigner_HighlightColor=ff46a2da
|
QmlDesigner_HighlightColor=ff46a2da
|
||||||
|
@@ -54,11 +54,18 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function prettyPrintScale(amount) {
|
function prettyPrintScale(amount) {
|
||||||
|
var sign;
|
||||||
|
if (amount < 0) {
|
||||||
|
sign = "-";
|
||||||
|
amount = -amount;
|
||||||
|
} else {
|
||||||
|
sign = "";
|
||||||
|
}
|
||||||
var unitOffset = 0;
|
var unitOffset = 0;
|
||||||
var unitAmount = 1;
|
var unitAmount = 1;
|
||||||
for (unitOffset = 0; amount > unitAmount * 1024; ++unitOffset, unitAmount *= 1024) {}
|
for (unitOffset = 0; amount > unitAmount * 1024; ++unitOffset, unitAmount *= 1024) {}
|
||||||
var result = amount / unitAmount;
|
var result = amount / unitAmount;
|
||||||
return roundTo3Digits(result) + units[unitOffset];
|
return sign + roundTo3Digits(result) + units[unitOffset];
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -134,7 +141,7 @@ Item {
|
|||||||
anchors.bottomMargin: 2
|
anchors.bottomMargin: 2
|
||||||
anchors.leftMargin: 2
|
anchors.leftMargin: 2
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
text: prettyPrintScale(index * row.stepVal)
|
text: prettyPrintScale(row.minVal + index * row.stepVal)
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
@@ -212,6 +212,11 @@ public:
|
|||||||
IconsCodeModelOverlayBackgroundColor,
|
IconsCodeModelOverlayBackgroundColor,
|
||||||
IconsCodeModelOverlayForegroundColor,
|
IconsCodeModelOverlayForegroundColor,
|
||||||
|
|
||||||
|
/* Code model text marks */
|
||||||
|
|
||||||
|
CodeModel_Error_TextMarkColor,
|
||||||
|
CodeModel_Warning_TextMarkColor,
|
||||||
|
|
||||||
/* Output panes */
|
/* Output panes */
|
||||||
|
|
||||||
OutputPanes_DebugTextColor,
|
OutputPanes_DebugTextColor,
|
||||||
@@ -287,10 +292,6 @@ public:
|
|||||||
ProjectExplorer_TaskError_TextMarkColor,
|
ProjectExplorer_TaskError_TextMarkColor,
|
||||||
ProjectExplorer_TaskWarn_TextMarkColor,
|
ProjectExplorer_TaskWarn_TextMarkColor,
|
||||||
|
|
||||||
/* ClangCodeModel Plugin */
|
|
||||||
ClangCodeModel_Error_TextMarkColor,
|
|
||||||
ClangCodeModel_Warning_TextMarkColor,
|
|
||||||
|
|
||||||
/* QmlDesigner Plugin */
|
/* QmlDesigner Plugin */
|
||||||
QmlDesigner_BackgroundColor,
|
QmlDesigner_BackgroundColor,
|
||||||
QmlDesigner_HighlightColor,
|
QmlDesigner_HighlightColor,
|
||||||
|
@@ -46,7 +46,6 @@ HEADERS += \
|
|||||||
android_global.h \
|
android_global.h \
|
||||||
androidbuildapkstep.h \
|
androidbuildapkstep.h \
|
||||||
androidbuildapkwidget.h \
|
androidbuildapkwidget.h \
|
||||||
androidrunnable.h \
|
|
||||||
androidtoolmanager.h \
|
androidtoolmanager.h \
|
||||||
androidsdkmanager.h \
|
androidsdkmanager.h \
|
||||||
androidavdmanager.h \
|
androidavdmanager.h \
|
||||||
@@ -94,7 +93,6 @@ SOURCES += \
|
|||||||
androidbuildapkstep.cpp \
|
androidbuildapkstep.cpp \
|
||||||
androidbuildapkwidget.cpp \
|
androidbuildapkwidget.cpp \
|
||||||
androidqtsupport.cpp \
|
androidqtsupport.cpp \
|
||||||
androidrunnable.cpp \
|
|
||||||
androidtoolmanager.cpp \
|
androidtoolmanager.cpp \
|
||||||
androidsdkmanager.cpp \
|
androidsdkmanager.cpp \
|
||||||
androidavdmanager.cpp \
|
androidavdmanager.cpp \
|
||||||
|
@@ -86,8 +86,6 @@ Project {
|
|||||||
"androidrunconfiguration.h",
|
"androidrunconfiguration.h",
|
||||||
"androidruncontrol.cpp",
|
"androidruncontrol.cpp",
|
||||||
"androidruncontrol.h",
|
"androidruncontrol.h",
|
||||||
"androidrunnable.cpp",
|
|
||||||
"androidrunnable.h",
|
|
||||||
"androidrunner.cpp",
|
"androidrunner.cpp",
|
||||||
"androidrunner.h",
|
"androidrunner.h",
|
||||||
"androidrunnerworker.cpp",
|
"androidrunnerworker.cpp",
|
||||||
|
@@ -297,6 +297,7 @@ bool AndroidAvdManager::startAvdAsync(const QString &avdName) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
QProcess *avdProcess = new QProcess();
|
QProcess *avdProcess = new QProcess();
|
||||||
|
avdProcess->setReadChannelMode(QProcess::MergedChannels);
|
||||||
QObject::connect(avdProcess,
|
QObject::connect(avdProcess,
|
||||||
static_cast<void (QProcess::*)(int)>(&QProcess::finished),
|
static_cast<void (QProcess::*)(int)>(&QProcess::finished),
|
||||||
avdProcess,
|
avdProcess,
|
||||||
|
@@ -232,3 +232,4 @@ private:
|
|||||||
|
|
||||||
} // namespace Android
|
} // namespace Android
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(Android::AndroidDeviceInfo)
|
||||||
|
@@ -51,9 +51,11 @@ const char ANDROID_SETTINGS_ID[] = "BB.Android Configurations";
|
|||||||
const char ANDROID_TOOLCHAIN_ID[] = "Qt4ProjectManager.ToolChain.Android";
|
const char ANDROID_TOOLCHAIN_ID[] = "Qt4ProjectManager.ToolChain.Android";
|
||||||
const char ANDROIDQT[] = "Qt4ProjectManager.QtVersion.Android";
|
const char ANDROIDQT[] = "Qt4ProjectManager.QtVersion.Android";
|
||||||
|
|
||||||
const char ANDROID_AMSTARTARGS_ASPECT[] = "Android.AmStartArgs";
|
const char ANDROID_AMSTARTARGS[] = "Android.AmStartArgs";
|
||||||
const char ANDROID_PRESTARTSHELLCMDLIST_ASPECT[] = "Android.PreStartShellCmdList";
|
// Note: Can be set on RunConfiguration using an aspect and/or
|
||||||
const char ANDROID_POSTSTARTSHELLCMDLIST_ASPECT[] = "Android.PostStartShellCmdList";
|
// the AndroidRunnerWorker using recordData()
|
||||||
|
const char ANDROID_PRESTARTSHELLCMDLIST[] = "Android.PreStartShellCmdList";
|
||||||
|
const char ANDROID_POSTFINISHSHELLCMDLIST[] = "Android.PostFinishShellCmdList";
|
||||||
|
|
||||||
const char ANDROID_DEVICE_TYPE[] = "Android.Device.Type";
|
const char ANDROID_DEVICE_TYPE[] = "Android.Device.Type";
|
||||||
const char ANDROID_DEVICE_ID[] = "Android Device";
|
const char ANDROID_DEVICE_ID[] = "Android Device";
|
||||||
@@ -69,6 +71,7 @@ const char ANDROID_DEPLOY_SETTINGS_FILE[] = "AndroidDeploySettingsFile";
|
|||||||
const char ANDROID_PACKAGE_SOURCE_DIR[] = "AndroidPackageSourceDir";
|
const char ANDROID_PACKAGE_SOURCE_DIR[] = "AndroidPackageSourceDir";
|
||||||
const char ANDROID_EXTRA_LIBS[] = "AndroidExtraLibs";
|
const char ANDROID_EXTRA_LIBS[] = "AndroidExtraLibs";
|
||||||
|
|
||||||
|
const char ANDROID_PACKAGENAME[] = "Android.PackageName";
|
||||||
const char ANDROID_PACKAGE_INSTALLATION_STEP_ID[] = "Qt4ProjectManager.AndroidPackageInstallationStep";
|
const char ANDROID_PACKAGE_INSTALLATION_STEP_ID[] = "Qt4ProjectManager.AndroidPackageInstallationStep";
|
||||||
|
|
||||||
} // namespace Constants;
|
} // namespace Constants;
|
||||||
|
@@ -111,20 +111,20 @@ AndroidRunConfiguration::AndroidRunConfiguration(Target *target, Core::Id id)
|
|||||||
: RunConfiguration(target, id)
|
: RunConfiguration(target, id)
|
||||||
{
|
{
|
||||||
auto amStartArgsAspect = new BaseStringAspect(this);
|
auto amStartArgsAspect = new BaseStringAspect(this);
|
||||||
amStartArgsAspect->setId(Constants::ANDROID_AMSTARTARGS_ASPECT);
|
amStartArgsAspect->setId(Constants::ANDROID_AMSTARTARGS);
|
||||||
amStartArgsAspect->setSettingsKey("Android.AmStartArgsKey");
|
amStartArgsAspect->setSettingsKey("Android.AmStartArgsKey");
|
||||||
amStartArgsAspect->setLabelText(tr("Activity manager start options:"));
|
amStartArgsAspect->setLabelText(tr("Activity manager start options:"));
|
||||||
amStartArgsAspect->setDisplayStyle(BaseStringAspect::LineEditDisplay);
|
amStartArgsAspect->setDisplayStyle(BaseStringAspect::LineEditDisplay);
|
||||||
addExtraAspect(amStartArgsAspect);
|
addExtraAspect(amStartArgsAspect);
|
||||||
|
|
||||||
auto preStartShellCmdAspect = new BaseStringListAspect(this);
|
auto preStartShellCmdAspect = new BaseStringListAspect(this);
|
||||||
preStartShellCmdAspect->setId(Constants::ANDROID_PRESTARTSHELLCMDLIST_ASPECT);
|
preStartShellCmdAspect->setId(Constants::ANDROID_PRESTARTSHELLCMDLIST);
|
||||||
preStartShellCmdAspect->setSettingsKey("Android.PreStartShellCmdListKey");
|
preStartShellCmdAspect->setSettingsKey("Android.PreStartShellCmdListKey");
|
||||||
preStartShellCmdAspect->setLabel(tr("Shell commands to run on Android device before application launch."));
|
preStartShellCmdAspect->setLabel(tr("Shell commands to run on Android device before application launch."));
|
||||||
addExtraAspect(preStartShellCmdAspect);
|
addExtraAspect(preStartShellCmdAspect);
|
||||||
|
|
||||||
auto postStartShellCmdAspect = new BaseStringListAspect(this);
|
auto postStartShellCmdAspect = new BaseStringListAspect(this);
|
||||||
postStartShellCmdAspect->setId(Constants::ANDROID_POSTSTARTSHELLCMDLIST_ASPECT);
|
postStartShellCmdAspect->setId(Constants::ANDROID_POSTFINISHSHELLCMDLIST);
|
||||||
postStartShellCmdAspect->setSettingsKey("Android.PostStartShellCmdListKey");
|
postStartShellCmdAspect->setSettingsKey("Android.PostStartShellCmdListKey");
|
||||||
postStartShellCmdAspect->setLabel(tr("Shell commands to run on Android device after application quits."));
|
postStartShellCmdAspect->setLabel(tr("Shell commands to run on Android device after application quits."));
|
||||||
addExtraAspect(postStartShellCmdAspect);
|
addExtraAspect(postStartShellCmdAspect);
|
||||||
@@ -140,7 +140,7 @@ QWidget *AndroidRunConfiguration::createConfigurationWidget()
|
|||||||
auto widget = new QWidget;
|
auto widget = new QWidget;
|
||||||
auto layout = new QFormLayout(widget);
|
auto layout = new QFormLayout(widget);
|
||||||
|
|
||||||
extraAspect(Constants::ANDROID_AMSTARTARGS_ASPECT)->addToConfigurationLayout(layout);
|
extraAspect(Constants::ANDROID_AMSTARTARGS)->addToConfigurationLayout(layout);
|
||||||
|
|
||||||
auto warningIconLabel = new QLabel;
|
auto warningIconLabel = new QLabel;
|
||||||
warningIconLabel->setPixmap(Utils::Icons::WARNING.pixmap());
|
warningIconLabel->setPixmap(Utils::Icons::WARNING.pixmap());
|
||||||
@@ -148,8 +148,8 @@ QWidget *AndroidRunConfiguration::createConfigurationWidget()
|
|||||||
auto warningLabel = new QLabel(tr("If the \"am start\" options conflict, the application might not start."));
|
auto warningLabel = new QLabel(tr("If the \"am start\" options conflict, the application might not start."));
|
||||||
layout->addRow(warningIconLabel, warningLabel);
|
layout->addRow(warningIconLabel, warningLabel);
|
||||||
|
|
||||||
extraAspect(Constants::ANDROID_PRESTARTSHELLCMDLIST_ASPECT)->addToConfigurationLayout(layout);
|
extraAspect(Constants::ANDROID_PRESTARTSHELLCMDLIST)->addToConfigurationLayout(layout);
|
||||||
extraAspect(Constants::ANDROID_POSTSTARTSHELLCMDLIST_ASPECT)->addToConfigurationLayout(layout);
|
extraAspect(Constants::ANDROID_POSTFINISHSHELLCMDLIST)->addToConfigurationLayout(layout);
|
||||||
|
|
||||||
auto wrapped = wrapWidget(widget);
|
auto wrapped = wrapWidget(widget);
|
||||||
auto detailsWidget = qobject_cast<DetailsWidget *>(wrapped);
|
auto detailsWidget = qobject_cast<DetailsWidget *>(wrapped);
|
||||||
|
@@ -1,37 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator.
|
|
||||||
**
|
|
||||||
** Commercial License Usage
|
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
|
||||||
** accordance with the commercial license agreement provided with the
|
|
||||||
** Software or, alternatively, in accordance with the terms contained in
|
|
||||||
** a written agreement between you and The Qt Company. For licensing terms
|
|
||||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
||||||
** information use the contact form at https://www.qt.io/contact-us.
|
|
||||||
**
|
|
||||||
** GNU General Public License Usage
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU
|
|
||||||
** General Public License version 3 as published by the Free Software
|
|
||||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
||||||
** included in the packaging of this file. Please review the following
|
|
||||||
** information to ensure the GNU General Public License requirements will
|
|
||||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#include "androidrunnable.h"
|
|
||||||
|
|
||||||
namespace Android {
|
|
||||||
|
|
||||||
void *AndroidRunnable::staticTypeId = &AndroidRunnable::staticTypeId;
|
|
||||||
|
|
||||||
AndroidRunnable::AndroidRunnable()
|
|
||||||
{
|
|
||||||
qRegisterMetaType<AndroidRunnable>("AndroidRunnable");
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Android
|
|
@@ -1,57 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
|
|
||||||
** Contact: https://www.qt.io/licensing/
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator.
|
|
||||||
**
|
|
||||||
** Commercial License Usage
|
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
|
||||||
** accordance with the commercial license agreement provided with the
|
|
||||||
** Software or, alternatively, in accordance with the terms contained in
|
|
||||||
** a written agreement between you and The Qt Company. For licensing terms
|
|
||||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
||||||
** information use the contact form at https://www.qt.io/contact-us.
|
|
||||||
**
|
|
||||||
** GNU General Public License Usage
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU
|
|
||||||
** General Public License version 3 as published by the Free Software
|
|
||||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
||||||
** included in the packaging of this file. Please review the following
|
|
||||||
** information to ensure the GNU General Public License requirements will
|
|
||||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "android_global.h"
|
|
||||||
#include <projectexplorer/runnables.h>
|
|
||||||
|
|
||||||
namespace Android {
|
|
||||||
|
|
||||||
struct ANDROID_EXPORT AndroidRunnable
|
|
||||||
{
|
|
||||||
AndroidRunnable();
|
|
||||||
QString packageName;
|
|
||||||
QStringList beforeStartAdbCommands;
|
|
||||||
QStringList afterFinishAdbCommands;
|
|
||||||
|
|
||||||
QString displayName() const { return packageName; }
|
|
||||||
static void *staticTypeId;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline bool operator==(const AndroidRunnable &r1, const AndroidRunnable &r2)
|
|
||||||
{
|
|
||||||
return r1.packageName == r2.packageName
|
|
||||||
&& r1.beforeStartAdbCommands == r2.beforeStartAdbCommands
|
|
||||||
&& r1.afterFinishAdbCommands == r2.afterFinishAdbCommands;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator!=(const AndroidRunnable &r1, const AndroidRunnable &r2)
|
|
||||||
{
|
|
||||||
return !(r1 == r2);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Android
|
|
||||||
Q_DECLARE_METATYPE(Android::AndroidRunnable)
|
|
@@ -120,7 +120,8 @@ AndroidRunner::AndroidRunner(RunControl *runControl,
|
|||||||
setDisplayName("AndroidRunner");
|
setDisplayName("AndroidRunner");
|
||||||
static const int metaTypes[] = {
|
static const int metaTypes[] = {
|
||||||
qRegisterMetaType<QVector<QStringList> >("QVector<QStringList>"),
|
qRegisterMetaType<QVector<QStringList> >("QVector<QStringList>"),
|
||||||
qRegisterMetaType<Utils::Port>("Utils::Port")
|
qRegisterMetaType<Utils::Port>("Utils::Port"),
|
||||||
|
qRegisterMetaType<AndroidDeviceInfo>("Android::AndroidDeviceInfo")
|
||||||
};
|
};
|
||||||
Q_UNUSED(metaTypes);
|
Q_UNUSED(metaTypes);
|
||||||
|
|
||||||
@@ -128,21 +129,10 @@ AndroidRunner::AndroidRunner(RunControl *runControl,
|
|||||||
connect(&m_checkAVDTimer, &QTimer::timeout, this, &AndroidRunner::checkAVD);
|
connect(&m_checkAVDTimer, &QTimer::timeout, this, &AndroidRunner::checkAVD);
|
||||||
|
|
||||||
QString intent = intentName.isEmpty() ? AndroidManager::intentName(m_target) : intentName;
|
QString intent = intentName.isEmpty() ? AndroidManager::intentName(m_target) : intentName;
|
||||||
m_androidRunnable.packageName = intent.left(intent.indexOf('/'));
|
m_packageName = intent.left(intent.indexOf('/'));
|
||||||
|
|
||||||
RunConfiguration *rc = runControl->runConfiguration();
|
|
||||||
if (auto aspect = rc->extraAspect(Constants::ANDROID_PRESTARTSHELLCMDLIST_ASPECT)) {
|
|
||||||
for (QString shellCmd : static_cast<BaseStringListAspect *>(aspect)->value())
|
|
||||||
m_androidRunnable.beforeStartAdbCommands.append(QString("shell %1").arg(shellCmd));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto aspect = rc->extraAspect(Constants::ANDROID_POSTSTARTSHELLCMDLIST_ASPECT)) {
|
|
||||||
for (QString shellCmd : static_cast<BaseStringListAspect *>(aspect)->value())
|
|
||||||
m_androidRunnable.afterFinishAdbCommands.append(QString("shell %1").arg(shellCmd));
|
|
||||||
}
|
|
||||||
|
|
||||||
const int apiLevel = AndroidManager::deviceApiLevel(m_target);
|
const int apiLevel = AndroidManager::deviceApiLevel(m_target);
|
||||||
m_worker.reset(new AndroidRunnerWorker(this, m_androidRunnable));
|
m_worker.reset(new AndroidRunnerWorker(this, m_packageName));
|
||||||
m_worker->setIntentName(intent);
|
m_worker->setIntentName(intent);
|
||||||
m_worker->setIsPreNougat(apiLevel <= 23);
|
m_worker->setIsPreNougat(apiLevel <= 23);
|
||||||
m_worker->setExtraAppParams(extraAppParams);
|
m_worker->setExtraAppParams(extraAppParams);
|
||||||
@@ -193,7 +183,7 @@ void AndroidRunner::stop()
|
|||||||
{
|
{
|
||||||
if (m_checkAVDTimer.isActive()) {
|
if (m_checkAVDTimer.isActive()) {
|
||||||
m_checkAVDTimer.stop();
|
m_checkAVDTimer.stop();
|
||||||
appendMessage("\n\n" + tr("\"%1\" terminated.").arg(m_androidRunnable.packageName),
|
appendMessage("\n\n" + tr("\"%1\" terminated.").arg(m_packageName),
|
||||||
Utils::DebugFormat);
|
Utils::DebugFormat);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -258,7 +248,7 @@ void AndroidRunner::launchAVD()
|
|||||||
emit androidDeviceInfoChanged(info);
|
emit androidDeviceInfoChanged(info);
|
||||||
if (info.isValid()) {
|
if (info.isValid()) {
|
||||||
AndroidAvdManager avdManager;
|
AndroidAvdManager avdManager;
|
||||||
if (avdManager.findAvd(info.avdname).isEmpty()) {
|
if (!info.avdname.isEmpty() && avdManager.findAvd(info.avdname).isEmpty()) {
|
||||||
bool launched = avdManager.startAvdAsync(info.avdname);
|
bool launched = avdManager.startAvdAsync(info.avdname);
|
||||||
m_launchedAVDName = launched ? info.avdname:"";
|
m_launchedAVDName = launched ? info.avdname:"";
|
||||||
} else {
|
} else {
|
||||||
|
@@ -26,7 +26,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "androidconfigurations.h"
|
#include "androidconfigurations.h"
|
||||||
#include "androidrunnable.h"
|
|
||||||
|
|
||||||
#include <projectexplorer/runconfiguration.h>
|
#include <projectexplorer/runconfiguration.h>
|
||||||
#include <qmldebug/qmldebugcommandlinearguments.h>
|
#include <qmldebug/qmldebugcommandlinearguments.h>
|
||||||
@@ -67,7 +66,7 @@ signals:
|
|||||||
void asyncStart();
|
void asyncStart();
|
||||||
void asyncStop();
|
void asyncStop();
|
||||||
void qmlServerReady(const QUrl &serverUrl);
|
void qmlServerReady(const QUrl &serverUrl);
|
||||||
void androidDeviceInfoChanged(const AndroidDeviceInfo &deviceInfo);
|
void androidDeviceInfoChanged(const Android::AndroidDeviceInfo &deviceInfo);
|
||||||
void avdDetected();
|
void avdDetected();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -80,7 +79,7 @@ private:
|
|||||||
void checkAVD();
|
void checkAVD();
|
||||||
void launchAVD();
|
void launchAVD();
|
||||||
|
|
||||||
AndroidRunnable m_androidRunnable;
|
QString m_packageName;
|
||||||
QString m_launchedAVDName;
|
QString m_launchedAVDName;
|
||||||
QThread m_thread;
|
QThread m_thread;
|
||||||
QTimer m_checkAVDTimer;
|
QTimer m_checkAVDTimer;
|
||||||
|
@@ -140,8 +140,8 @@ static void deleter(QProcess *p)
|
|||||||
p->deleteLater();
|
p->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const AndroidRunnable &runnable)
|
AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const QString &packageName)
|
||||||
: m_androidRunnable(runnable)
|
: m_packageName(packageName)
|
||||||
, m_adbLogcatProcess(nullptr, deleter)
|
, m_adbLogcatProcess(nullptr, deleter)
|
||||||
, m_psIsAlive(nullptr, deleter)
|
, m_psIsAlive(nullptr, deleter)
|
||||||
, m_logCatRegExp(regExpLogcat)
|
, m_logCatRegExp(regExpLogcat)
|
||||||
@@ -181,8 +181,22 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const AndroidRunnabl
|
|||||||
m_deviceSerialNumber = AndroidManager::deviceSerialNumber(target);
|
m_deviceSerialNumber = AndroidManager::deviceSerialNumber(target);
|
||||||
m_apiLevel = AndroidManager::deviceApiLevel(target);
|
m_apiLevel = AndroidManager::deviceApiLevel(target);
|
||||||
|
|
||||||
if (auto aspect = runConfig->extraAspect(Constants::ANDROID_AMSTARTARGS_ASPECT))
|
if (auto aspect = runConfig->extraAspect(Constants::ANDROID_AMSTARTARGS))
|
||||||
m_amStartExtraArgs = static_cast<BaseStringAspect *>(aspect)->value().split(' ');
|
m_amStartExtraArgs = static_cast<BaseStringAspect *>(aspect)->value().split(' ');
|
||||||
|
|
||||||
|
if (auto aspect = runConfig->extraAspect(Constants::ANDROID_PRESTARTSHELLCMDLIST)) {
|
||||||
|
for (const QString &shellCmd : static_cast<BaseStringListAspect *>(aspect)->value())
|
||||||
|
m_beforeStartAdbCommands.append(QString("shell %1").arg(shellCmd));
|
||||||
|
}
|
||||||
|
for (const QString &shellCmd : runner->recordedData(Constants::ANDROID_PRESTARTSHELLCMDLIST).toStringList())
|
||||||
|
m_beforeStartAdbCommands.append(QString("shell %1").arg(shellCmd));
|
||||||
|
|
||||||
|
if (auto aspect = runConfig->extraAspect(Constants::ANDROID_POSTFINISHSHELLCMDLIST)) {
|
||||||
|
for (const QString &shellCmd : static_cast<BaseStringListAspect *>(aspect)->value())
|
||||||
|
m_afterFinishAdbCommands.append(QString("shell %1").arg(shellCmd));
|
||||||
|
}
|
||||||
|
for (const QString &shellCmd : runner->recordedData(Constants::ANDROID_POSTFINISHSHELLCMDLIST).toStringList())
|
||||||
|
m_afterFinishAdbCommands.append(QString("shell %1").arg(shellCmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
AndroidRunnerWorker::~AndroidRunnerWorker()
|
AndroidRunnerWorker::~AndroidRunnerWorker()
|
||||||
@@ -229,7 +243,7 @@ bool AndroidRunnerWorker::runAdb(const QStringList &args, int timeoutS)
|
|||||||
void AndroidRunnerWorker::adbKill(qint64 pid)
|
void AndroidRunnerWorker::adbKill(qint64 pid)
|
||||||
{
|
{
|
||||||
runAdb({"shell", "kill", "-9", QString::number(pid)});
|
runAdb({"shell", "kill", "-9", QString::number(pid)});
|
||||||
runAdb({"shell", "run-as", m_androidRunnable.packageName, "kill", "-9", QString::number(pid)});
|
runAdb({"shell", "run-as", m_packageName, "kill", "-9", QString::number(pid)});
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList AndroidRunnerWorker::selector() const
|
QStringList AndroidRunnerWorker::selector() const
|
||||||
@@ -239,14 +253,14 @@ QStringList AndroidRunnerWorker::selector() const
|
|||||||
|
|
||||||
void AndroidRunnerWorker::forceStop()
|
void AndroidRunnerWorker::forceStop()
|
||||||
{
|
{
|
||||||
runAdb({"shell", "am", "force-stop", m_androidRunnable.packageName}, 30);
|
runAdb({"shell", "am", "force-stop", m_packageName}, 30);
|
||||||
|
|
||||||
// try killing it via kill -9
|
// try killing it via kill -9
|
||||||
const QByteArray out = Utils::SynchronousProcess()
|
const QByteArray out = Utils::SynchronousProcess()
|
||||||
.runBlocking(m_adb, selector() << QStringLiteral("shell") << pidScriptPreNougat)
|
.runBlocking(m_adb, selector() << QStringLiteral("shell") << pidScriptPreNougat)
|
||||||
.allRawOutput();
|
.allRawOutput();
|
||||||
|
|
||||||
qint64 pid = extractPID(out.simplified(), m_androidRunnable.packageName);
|
qint64 pid = extractPID(out.simplified(), m_packageName);
|
||||||
if (pid != -1) {
|
if (pid != -1) {
|
||||||
adbKill(pid);
|
adbKill(pid);
|
||||||
}
|
}
|
||||||
@@ -346,7 +360,7 @@ void AndroidRunnerWorker::asyncStartHelper()
|
|||||||
QTC_ASSERT(!m_adbLogcatProcess, /**/);
|
QTC_ASSERT(!m_adbLogcatProcess, /**/);
|
||||||
m_adbLogcatProcess = std::move(logcatProcess);
|
m_adbLogcatProcess = std::move(logcatProcess);
|
||||||
|
|
||||||
for (const QString &entry: m_androidRunnable.beforeStartAdbCommands)
|
for (const QString &entry : m_beforeStartAdbCommands)
|
||||||
runAdb(entry.split(' ', QString::SkipEmptyParts));
|
runAdb(entry.split(' ', QString::SkipEmptyParts));
|
||||||
|
|
||||||
QStringList args({"shell", "am", "start"});
|
QStringList args({"shell", "am", "start"});
|
||||||
@@ -356,14 +370,14 @@ void AndroidRunnerWorker::asyncStartHelper()
|
|||||||
args << "-D";
|
args << "-D";
|
||||||
QString gdbServerSocket;
|
QString gdbServerSocket;
|
||||||
// run-as <package-name> pwd fails on API 22 so route the pwd through shell.
|
// run-as <package-name> pwd fails on API 22 so route the pwd through shell.
|
||||||
if (!runAdb({"shell", "run-as", m_androidRunnable.packageName, "/system/bin/sh", "-c", "pwd"})) {
|
if (!runAdb({"shell", "run-as", m_packageName, "/system/bin/sh", "-c", "pwd"})) {
|
||||||
emit remoteProcessFinished(tr("Failed to get process path. Reason: %1.").arg(m_lastRunAdbError));
|
emit remoteProcessFinished(tr("Failed to get process path. Reason: %1.").arg(m_lastRunAdbError));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gdbServerSocket = QString::fromUtf8(m_lastRunAdbRawOutput.trimmed()) + "/debug-socket";
|
gdbServerSocket = QString::fromUtf8(m_lastRunAdbRawOutput.trimmed()) + "/debug-socket";
|
||||||
|
|
||||||
QString gdbServerExecutable;
|
QString gdbServerExecutable;
|
||||||
if (!runAdb({"shell", "run-as", m_androidRunnable.packageName, "ls", "lib/"})) {
|
if (!runAdb({"shell", "run-as", m_packageName, "ls", "lib/"})) {
|
||||||
emit remoteProcessFinished(tr("Failed to get process path. Reason: %1.").arg(m_lastRunAdbError));
|
emit remoteProcessFinished(tr("Failed to get process path. Reason: %1.").arg(m_lastRunAdbError));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -380,11 +394,11 @@ void AndroidRunnerWorker::asyncStartHelper()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
runAdb({"shell", "run-as", m_androidRunnable.packageName, "killall", gdbServerExecutable});
|
runAdb({"shell", "run-as", m_packageName, "killall", gdbServerExecutable});
|
||||||
runAdb({"shell", "run-as", m_androidRunnable.packageName, "rm", gdbServerSocket});
|
runAdb({"shell", "run-as", m_packageName, "rm", gdbServerSocket});
|
||||||
std::unique_ptr<QProcess, Deleter> gdbServerProcess(new QProcess, deleter);
|
std::unique_ptr<QProcess, Deleter> gdbServerProcess(new QProcess, deleter);
|
||||||
gdbServerProcess->start(m_adb, selector() << "shell" << "run-as"
|
gdbServerProcess->start(m_adb, selector() << "shell" << "run-as"
|
||||||
<< m_androidRunnable.packageName << "lib/" + gdbServerExecutable
|
<< m_packageName << "lib/" + gdbServerExecutable
|
||||||
<< "--multi" << "+" + gdbServerSocket);
|
<< "--multi" << "+" + gdbServerSocket);
|
||||||
if (!gdbServerProcess->waitForStarted()) {
|
if (!gdbServerProcess->waitForStarted()) {
|
||||||
emit remoteProcessFinished(tr("Failed to start C++ debugger."));
|
emit remoteProcessFinished(tr("Failed to start C++ debugger."));
|
||||||
@@ -398,7 +412,7 @@ void AndroidRunnerWorker::asyncStartHelper()
|
|||||||
emit remoteProcessFinished(tr("Failed to forward C++ debugging ports. Reason: %1.").arg(m_lastRunAdbError));
|
emit remoteProcessFinished(tr("Failed to forward C++ debugging ports. Reason: %1.").arg(m_lastRunAdbError));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_androidRunnable.afterFinishAdbCommands.push_back(removeForward.join(' '));
|
m_afterFinishAdbCommands.push_back(removeForward.join(' '));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_qmlDebugServices != QmlDebug::NoQmlDebugServices) {
|
if (m_qmlDebugServices != QmlDebug::NoQmlDebugServices) {
|
||||||
@@ -411,7 +425,7 @@ void AndroidRunnerWorker::asyncStartHelper()
|
|||||||
.arg(m_lastRunAdbError));
|
.arg(m_lastRunAdbError));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_androidRunnable.afterFinishAdbCommands.push_back(removeForward.join(' '));
|
m_afterFinishAdbCommands.push_back(removeForward.join(' '));
|
||||||
|
|
||||||
args << "-e" << "qml_debug" << "true"
|
args << "-e" << "qml_debug" << "true"
|
||||||
<< "-e" << "qmljsdebugger"
|
<< "-e" << "qmljsdebugger"
|
||||||
@@ -442,7 +456,7 @@ void AndroidRunnerWorker::asyncStart()
|
|||||||
asyncStartHelper();
|
asyncStartHelper();
|
||||||
|
|
||||||
m_pidFinder = Utils::onResultReady(Utils::runAsync(findProcessPID, m_adb, selector(),
|
m_pidFinder = Utils::onResultReady(Utils::runAsync(findProcessPID, m_adb, selector(),
|
||||||
m_androidRunnable.packageName, m_isPreNougat),
|
m_packageName, m_isPreNougat),
|
||||||
bind(&AndroidRunnerWorker::onProcessIdChanged, this, _1));
|
bind(&AndroidRunnerWorker::onProcessIdChanged, this, _1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,7 +481,7 @@ void AndroidRunnerWorker::handleJdbWaiting()
|
|||||||
emit remoteProcessFinished(tr("Failed to forward jdb debugging ports. Reason: %1.").arg(m_lastRunAdbError));
|
emit remoteProcessFinished(tr("Failed to forward jdb debugging ports. Reason: %1.").arg(m_lastRunAdbError));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_androidRunnable.afterFinishAdbCommands.push_back(removeForward.join(' '));
|
m_afterFinishAdbCommands.push_back(removeForward.join(' '));
|
||||||
|
|
||||||
auto jdbPath = AndroidConfigurations::currentConfig().openJDKLocation().appendPath("bin");
|
auto jdbPath = AndroidConfigurations::currentConfig().openJDKLocation().appendPath("bin");
|
||||||
if (Utils::HostOsInfo::isWindowsHost())
|
if (Utils::HostOsInfo::isWindowsHost())
|
||||||
@@ -527,7 +541,7 @@ void AndroidRunnerWorker::onProcessIdChanged(qint64 pid)
|
|||||||
m_processPID = pid;
|
m_processPID = pid;
|
||||||
if (pid == -1) {
|
if (pid == -1) {
|
||||||
emit remoteProcessFinished(QLatin1String("\n\n") + tr("\"%1\" died.")
|
emit remoteProcessFinished(QLatin1String("\n\n") + tr("\"%1\" died.")
|
||||||
.arg(m_androidRunnable.packageName));
|
.arg(m_packageName));
|
||||||
// App died/killed. Reset log, monitor, jdb & gdb processes.
|
// App died/killed. Reset log, monitor, jdb & gdb processes.
|
||||||
m_adbLogcatProcess.reset();
|
m_adbLogcatProcess.reset();
|
||||||
m_psIsAlive.reset();
|
m_psIsAlive.reset();
|
||||||
@@ -535,7 +549,7 @@ void AndroidRunnerWorker::onProcessIdChanged(qint64 pid)
|
|||||||
m_gdbServerProcess.reset();
|
m_gdbServerProcess.reset();
|
||||||
|
|
||||||
// Run adb commands after application quit.
|
// Run adb commands after application quit.
|
||||||
for (const QString &entry: m_androidRunnable.afterFinishAdbCommands)
|
for (const QString &entry: m_afterFinishAdbCommands)
|
||||||
runAdb(entry.split(' ', QString::SkipEmptyParts));
|
runAdb(entry.split(' ', QString::SkipEmptyParts));
|
||||||
} else {
|
} else {
|
||||||
// In debugging cases this will be funneled to the engine to actually start
|
// In debugging cases this will be funneled to the engine to actually start
|
||||||
|
@@ -26,12 +26,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <projectexplorer/runconfiguration.h>
|
||||||
|
|
||||||
#include <qmldebug/qmldebugcommandlinearguments.h>
|
#include <qmldebug/qmldebugcommandlinearguments.h>
|
||||||
|
|
||||||
#include <QFuture>
|
#include <QFuture>
|
||||||
|
|
||||||
#include "androidrunnable.h"
|
|
||||||
|
|
||||||
namespace Android {
|
namespace Android {
|
||||||
|
|
||||||
class AndroidDeviceInfo;
|
class AndroidDeviceInfo;
|
||||||
@@ -44,7 +44,7 @@ class AndroidRunnerWorker : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
AndroidRunnerWorker(ProjectExplorer::RunWorker *runner, const AndroidRunnable &runnable);
|
AndroidRunnerWorker(ProjectExplorer::RunWorker *runner, const QString &packageName);
|
||||||
~AndroidRunnerWorker() override;
|
~AndroidRunnerWorker() override;
|
||||||
bool adbShellAmNeedsQuotes();
|
bool adbShellAmNeedsQuotes();
|
||||||
bool runAdb(const QStringList &args, int timeoutS = 10);
|
bool runAdb(const QStringList &args, int timeoutS = 10);
|
||||||
@@ -85,8 +85,10 @@ protected:
|
|||||||
|
|
||||||
// Create the processes and timer in the worker thread, for correct thread affinity
|
// Create the processes and timer in the worker thread, for correct thread affinity
|
||||||
bool m_isPreNougat = false;
|
bool m_isPreNougat = false;
|
||||||
AndroidRunnable m_androidRunnable;
|
QString m_packageName;
|
||||||
QString m_intentName;
|
QString m_intentName;
|
||||||
|
QStringList m_beforeStartAdbCommands;
|
||||||
|
QStringList m_afterFinishAdbCommands;
|
||||||
QString m_adb;
|
QString m_adb;
|
||||||
QStringList m_amStartExtraArgs;
|
QStringList m_amStartExtraArgs;
|
||||||
qint64 m_processPID = -1;
|
qint64 m_processPID = -1;
|
||||||
|
@@ -48,7 +48,6 @@
|
|||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
#include <utils/outputformat.h>
|
#include <utils/outputformat.h>
|
||||||
#include <utils/qtcprocess.h>
|
#include <utils/qtcprocess.h>
|
||||||
#include <utils/runextensions.h>
|
|
||||||
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
@@ -56,8 +55,9 @@
|
|||||||
#include <QFuture>
|
#include <QFuture>
|
||||||
#include <QFutureInterface>
|
#include <QFutureInterface>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QProcess>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QTime>
|
#include <QTimer>
|
||||||
|
|
||||||
#include <debugger/debuggerkitinformation.h>
|
#include <debugger/debuggerkitinformation.h>
|
||||||
#include <debugger/debuggerruncontrol.h>
|
#include <debugger/debuggerruncontrol.h>
|
||||||
@@ -88,9 +88,9 @@ TestRunner::TestRunner(QObject *parent) :
|
|||||||
&m_futureWatcher, &QFutureWatcher<TestResultPtr>::cancel);
|
&m_futureWatcher, &QFutureWatcher<TestResultPtr>::cancel);
|
||||||
connect(&m_futureWatcher, &QFutureWatcher<TestResultPtr>::canceled,
|
connect(&m_futureWatcher, &QFutureWatcher<TestResultPtr>::canceled,
|
||||||
this, [this]() {
|
this, [this]() {
|
||||||
|
cancelCurrent(UserCanceled);
|
||||||
emit testResultReady(TestResultPtr(new FaultyTestResult(
|
emit testResultReady(TestResultPtr(new FaultyTestResult(
|
||||||
Result::MessageFatal, tr("Test run canceled by user."))));
|
Result::MessageFatal, tr("Test run canceled by user."))));
|
||||||
m_executingTests = false; // avoid being stuck if finished() signal won't get emitted
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,13 +103,15 @@ TestRunner::~TestRunner()
|
|||||||
|
|
||||||
void TestRunner::setSelectedTests(const QList<TestConfiguration *> &selected)
|
void TestRunner::setSelectedTests(const QList<TestConfiguration *> &selected)
|
||||||
{
|
{
|
||||||
qDeleteAll(m_selectedTests);
|
QTC_ASSERT(!m_executingTests, return);
|
||||||
m_selectedTests.clear();
|
qDeleteAll(m_selectedTests);
|
||||||
m_selectedTests = selected;
|
m_selectedTests.clear();
|
||||||
|
m_selectedTests.append(selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestRunner::runTest(TestRunMode mode, const TestTreeItem *item)
|
void TestRunner::runTest(TestRunMode mode, const TestTreeItem *item)
|
||||||
{
|
{
|
||||||
|
QTC_ASSERT(!m_executingTests, return);
|
||||||
TestConfiguration *configuration = item->asConfiguration(mode);
|
TestConfiguration *configuration = item->asConfiguration(mode);
|
||||||
|
|
||||||
if (configuration) {
|
if (configuration) {
|
||||||
@@ -118,15 +120,16 @@ void TestRunner::runTest(TestRunMode mode, const TestTreeItem *item)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString processInformation(const QProcess &proc)
|
static QString processInformation(const QProcess *proc)
|
||||||
{
|
{
|
||||||
QString information("\nCommand line: " + proc.program() + ' ' + proc.arguments().join(' '));
|
QTC_ASSERT(proc, return QString());
|
||||||
|
QString information("\nCommand line: " + proc->program() + ' ' + proc->arguments().join(' '));
|
||||||
QStringList important = { "PATH" };
|
QStringList important = { "PATH" };
|
||||||
if (Utils::HostOsInfo::isLinuxHost())
|
if (Utils::HostOsInfo::isLinuxHost())
|
||||||
important.append("LD_LIBRARY_PATH");
|
important.append("LD_LIBRARY_PATH");
|
||||||
else if (Utils::HostOsInfo::isMacHost())
|
else if (Utils::HostOsInfo::isMacHost())
|
||||||
important.append({ "DYLD_LIBRARY_PATH", "DYLD_FRAMEWORK_PATH" });
|
important.append({ "DYLD_LIBRARY_PATH", "DYLD_FRAMEWORK_PATH" });
|
||||||
const QProcessEnvironment &environment = proc.processEnvironment();
|
const QProcessEnvironment &environment = proc->processEnvironment();
|
||||||
for (const QString &var : important)
|
for (const QString &var : important)
|
||||||
information.append('\n' + var + ": " + environment.value(var));
|
information.append('\n' + var + ": " + environment.value(var));
|
||||||
return information;
|
return information;
|
||||||
@@ -142,133 +145,131 @@ static QString rcInfo(const TestConfiguration * const config)
|
|||||||
|
|
||||||
static QString constructOmittedDetailsString(const QStringList &omitted)
|
static QString constructOmittedDetailsString(const QStringList &omitted)
|
||||||
{
|
{
|
||||||
QString details = TestRunner::tr("Omitted the following arguments specified on the run "
|
return TestRunner::tr("Omitted the following arguments specified on the run "
|
||||||
"configuration page for \"%1\":");
|
"configuration page for \"%1\":") + '\n' + omitted.join('\n');
|
||||||
for (const QString &arg : omitted)
|
|
||||||
details += "\n" + arg;
|
|
||||||
return details;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void performTestRun(QFutureInterface<TestResultPtr> &futureInterface,
|
void TestRunner::scheduleNext()
|
||||||
const QList<TestConfiguration *> selectedTests,
|
|
||||||
const TestSettings &settings)
|
|
||||||
{
|
{
|
||||||
const int timeout = settings.timeout;
|
QTC_ASSERT(!m_selectedTests.isEmpty(), onFinished(); return);
|
||||||
const bool omitRunConfigWarnings = settings.omitRunConfigWarn;
|
QTC_ASSERT(!m_currentConfig && !m_currentProcess, resetInternalPointers());
|
||||||
QEventLoop eventLoop;
|
QTC_ASSERT(m_fakeFutureInterface, onFinished(); return);
|
||||||
int testCaseCount = 0;
|
|
||||||
for (TestConfiguration *config : selectedTests) {
|
m_currentConfig = m_selectedTests.dequeue();
|
||||||
config->completeTestInformation(TestRunMode::Run);
|
|
||||||
if (config->project()) {
|
QString commandFilePath = m_currentConfig->executableFilePath();
|
||||||
testCaseCount += config->testCaseCount();
|
if (commandFilePath.isEmpty()) {
|
||||||
if (!omitRunConfigWarnings && config->isGuessed()) {
|
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
|
||||||
QString message = TestRunner::tr(
|
tr("Executable path is empty. (%1)").arg(m_currentConfig->displayName()))));
|
||||||
"Project's run configuration was guessed for \"%1\".\n"
|
delete m_currentConfig;
|
||||||
"This might cause trouble during execution.\n"
|
m_currentConfig = nullptr;
|
||||||
"(guessed from \"%2\")");
|
if (m_selectedTests.isEmpty())
|
||||||
message = message.arg(config->displayName()).arg(config->runConfigDisplayName());
|
onFinished();
|
||||||
futureInterface.reportResult(
|
else
|
||||||
TestResultPtr(new FaultyTestResult(Result::MessageWarn, message)));
|
onProcessFinished();
|
||||||
}
|
return;
|
||||||
} else {
|
}
|
||||||
futureInterface.reportResult(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
|
if (!m_currentConfig->project())
|
||||||
TestRunner::tr("Project is null for \"%1\". Removing from test run.\n"
|
onProcessFinished();
|
||||||
"Check the test environment.").arg(config->displayName()))));
|
|
||||||
|
m_currentProcess = new QProcess;
|
||||||
|
m_currentProcess->setReadChannel(QProcess::StandardOutput);
|
||||||
|
m_currentProcess->setProgram(commandFilePath);
|
||||||
|
|
||||||
|
QTC_ASSERT(!m_currentOutputReader, delete m_currentOutputReader);
|
||||||
|
m_currentOutputReader = m_currentConfig->outputReader(*m_fakeFutureInterface, m_currentProcess);
|
||||||
|
QTC_ASSERT(m_currentOutputReader, onProcessFinished();return);
|
||||||
|
|
||||||
|
connect(m_currentOutputReader, &TestOutputReader::newOutputAvailable,
|
||||||
|
TestResultsPane::instance(), &TestResultsPane::addOutput);
|
||||||
|
|
||||||
|
|
||||||
|
QStringList omitted;
|
||||||
|
m_currentProcess->setArguments(m_currentConfig->argumentsForTestRunner(&omitted));
|
||||||
|
if (!omitted.isEmpty()) {
|
||||||
|
const QString &details = constructOmittedDetailsString(omitted);
|
||||||
|
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
|
||||||
|
details.arg(m_currentConfig->displayName()))));
|
||||||
|
}
|
||||||
|
m_currentProcess->setWorkingDirectory(m_currentConfig->workingDirectory());
|
||||||
|
QProcessEnvironment environment = m_currentConfig->environment().toProcessEnvironment();
|
||||||
|
if (Utils::HostOsInfo::isWindowsHost())
|
||||||
|
environment.insert("QT_LOGGING_TO_CONSOLE", "1");
|
||||||
|
const int timeout = AutotestPlugin::settings()->timeout;
|
||||||
|
if (timeout > 5 * 60 * 1000) // Qt5.5 introduced hard limit, Qt5.6.1 added env var to raise this
|
||||||
|
environment.insert("QTEST_FUNCTION_TIMEOUT", QString::number(timeout));
|
||||||
|
m_currentProcess->setProcessEnvironment(environment);
|
||||||
|
|
||||||
|
connect(m_currentProcess,
|
||||||
|
static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
|
||||||
|
this, &TestRunner::onProcessFinished);
|
||||||
|
QTimer::singleShot(timeout, m_currentProcess, [this]() { cancelCurrent(Timeout); });
|
||||||
|
|
||||||
|
m_currentProcess->start();
|
||||||
|
if (!m_currentProcess->waitForStarted()) {
|
||||||
|
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
|
||||||
|
tr("Failed to start test for project \"%1\".").arg(m_currentConfig->displayName())
|
||||||
|
+ processInformation(m_currentProcess) + rcInfo(m_currentConfig))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestRunner::cancelCurrent(TestRunner::CancelReason reason)
|
||||||
|
{
|
||||||
|
if (reason == UserCanceled) {
|
||||||
|
if (!m_fakeFutureInterface->isCanceled()) // depends on using the button / progress bar
|
||||||
|
m_fakeFutureInterface->reportCanceled();
|
||||||
|
}
|
||||||
|
if (m_currentProcess && m_currentProcess->state() != QProcess::NotRunning) {
|
||||||
|
m_currentProcess->kill();
|
||||||
|
m_currentProcess->waitForFinished();
|
||||||
|
}
|
||||||
|
if (reason == Timeout) {
|
||||||
|
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
|
||||||
|
tr("Test case canceled due to timeout.\nMaybe raise the timeout?"))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestRunner::onProcessFinished()
|
||||||
|
{
|
||||||
|
m_fakeFutureInterface->setProgressValue(m_fakeFutureInterface->progressValue()
|
||||||
|
+ m_currentConfig->testCaseCount());
|
||||||
|
if (!m_fakeFutureInterface->isCanceled()) {
|
||||||
|
if (m_currentProcess->exitStatus() == QProcess::CrashExit) {
|
||||||
|
m_currentOutputReader->reportCrash();
|
||||||
|
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
|
||||||
|
tr("Test for project \"%1\" crashed.").arg(m_currentConfig->displayName())
|
||||||
|
+ processInformation(m_currentProcess) + rcInfo(m_currentConfig))));
|
||||||
|
} else if (!m_currentOutputReader->hadValidOutput()) {
|
||||||
|
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
|
||||||
|
tr("Test for project \"%1\" did not produce any expected output.")
|
||||||
|
.arg(m_currentConfig->displayName()) + processInformation(m_currentProcess)
|
||||||
|
+ rcInfo(m_currentConfig))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QProcess testProcess;
|
resetInternalPointers();
|
||||||
testProcess.setReadChannel(QProcess::StandardOutput);
|
|
||||||
|
|
||||||
futureInterface.setProgressRange(0, testCaseCount);
|
if (!m_selectedTests.isEmpty() && !m_fakeFutureInterface->isCanceled()) {
|
||||||
futureInterface.setProgressValue(0);
|
scheduleNext();
|
||||||
|
} else {
|
||||||
for (const TestConfiguration *testConfiguration : selectedTests) {
|
m_fakeFutureInterface->reportFinished();
|
||||||
QString commandFilePath = testConfiguration->executableFilePath();
|
onFinished();
|
||||||
if (commandFilePath.isEmpty()) {
|
|
||||||
futureInterface.reportResult(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
|
|
||||||
TestRunner::tr("Executable path is empty. (%1)")
|
|
||||||
.arg(testConfiguration->displayName()))));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
testProcess.setProgram(commandFilePath);
|
|
||||||
|
|
||||||
QScopedPointer<TestOutputReader> outputReader;
|
|
||||||
outputReader.reset(testConfiguration->outputReader(futureInterface, &testProcess));
|
|
||||||
QTC_ASSERT(outputReader, continue);
|
|
||||||
TestRunner::connect(outputReader.data(), &TestOutputReader::newOutputAvailable,
|
|
||||||
TestResultsPane::instance(), &TestResultsPane::addOutput);
|
|
||||||
if (futureInterface.isCanceled())
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!testConfiguration->project())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
QStringList omitted;
|
|
||||||
testProcess.setArguments(testConfiguration->argumentsForTestRunner(&omitted));
|
|
||||||
if (!omitted.isEmpty()) {
|
|
||||||
const QString &details = constructOmittedDetailsString(omitted);
|
|
||||||
futureInterface.reportResult(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
|
|
||||||
details.arg(testConfiguration->displayName()))));
|
|
||||||
}
|
|
||||||
testProcess.setWorkingDirectory(testConfiguration->workingDirectory());
|
|
||||||
QProcessEnvironment environment = testConfiguration->environment().toProcessEnvironment();
|
|
||||||
if (Utils::HostOsInfo::isWindowsHost())
|
|
||||||
environment.insert("QT_LOGGING_TO_CONSOLE", "1");
|
|
||||||
testProcess.setProcessEnvironment(environment);
|
|
||||||
testProcess.start();
|
|
||||||
|
|
||||||
bool ok = testProcess.waitForStarted();
|
|
||||||
QTime executionTimer;
|
|
||||||
executionTimer.start();
|
|
||||||
bool canceledByTimeout = false;
|
|
||||||
if (ok) {
|
|
||||||
while (testProcess.state() == QProcess::Running) {
|
|
||||||
if (executionTimer.elapsed() >= timeout) {
|
|
||||||
canceledByTimeout = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (futureInterface.isCanceled()) {
|
|
||||||
testProcess.kill();
|
|
||||||
testProcess.waitForFinished();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
eventLoop.processEvents();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
futureInterface.reportResult(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
|
|
||||||
TestRunner::tr("Failed to start test for project \"%1\".")
|
|
||||||
.arg(testConfiguration->displayName()) + processInformation(testProcess)
|
|
||||||
+ rcInfo(testConfiguration))));
|
|
||||||
}
|
|
||||||
if (testProcess.exitStatus() == QProcess::CrashExit) {
|
|
||||||
outputReader->reportCrash();
|
|
||||||
futureInterface.reportResult(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
|
|
||||||
TestRunner::tr("Test for project \"%1\" crashed.")
|
|
||||||
.arg(testConfiguration->displayName()) + processInformation(testProcess)
|
|
||||||
+ rcInfo(testConfiguration))));
|
|
||||||
} else if (!outputReader->hadValidOutput()) {
|
|
||||||
futureInterface.reportResult(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
|
|
||||||
TestRunner::tr("Test for project \"%1\" did not produce any expected output.")
|
|
||||||
.arg(testConfiguration->displayName()) + processInformation(testProcess)
|
|
||||||
+ rcInfo(testConfiguration))));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (canceledByTimeout) {
|
|
||||||
if (testProcess.state() != QProcess::NotRunning) {
|
|
||||||
testProcess.kill();
|
|
||||||
testProcess.waitForFinished();
|
|
||||||
}
|
|
||||||
futureInterface.reportResult(TestResultPtr(
|
|
||||||
new FaultyTestResult(Result::MessageFatal, TestRunner::tr(
|
|
||||||
"Test case canceled due to timeout.\nMaybe raise the timeout?"))));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
futureInterface.setProgressValue(testCaseCount);
|
}
|
||||||
|
|
||||||
|
void TestRunner::resetInternalPointers()
|
||||||
|
{
|
||||||
|
delete m_currentOutputReader;
|
||||||
|
delete m_currentProcess;
|
||||||
|
delete m_currentConfig;
|
||||||
|
m_currentOutputReader = nullptr;
|
||||||
|
m_currentProcess = nullptr;
|
||||||
|
m_currentConfig = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestRunner::prepareToRunTests(TestRunMode mode)
|
void TestRunner::prepareToRunTests(TestRunMode mode)
|
||||||
{
|
{
|
||||||
|
QTC_ASSERT(!m_executingTests, return);
|
||||||
m_runMode = mode;
|
m_runMode = mode;
|
||||||
ProjectExplorer::Internal::ProjectExplorerSettings projectExplorerSettings =
|
ProjectExplorer::Internal::ProjectExplorerSettings projectExplorerSettings =
|
||||||
ProjectExplorer::ProjectExplorerPlugin::projectExplorerSettings();
|
ProjectExplorer::ProjectExplorerPlugin::projectExplorerSettings();
|
||||||
@@ -358,6 +359,32 @@ static ProjectExplorer::RunConfiguration *getRunConfiguration(const QString &dia
|
|||||||
return runConfig;
|
return runConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int TestRunner::precheckTestConfigurations()
|
||||||
|
{
|
||||||
|
const bool omitWarnings = AutotestPlugin::settings()->omitRunConfigWarn;
|
||||||
|
int testCaseCount = 0;
|
||||||
|
for (TestConfiguration *config : m_selectedTests) {
|
||||||
|
config->completeTestInformation(TestRunMode::Run);
|
||||||
|
if (config->project()) {
|
||||||
|
testCaseCount += config->testCaseCount();
|
||||||
|
if (!omitWarnings && config->isGuessed()) {
|
||||||
|
QString message = tr(
|
||||||
|
"Project's run configuration was guessed for \"%1\".\n"
|
||||||
|
"This might cause trouble during execution.\n"
|
||||||
|
"(guessed from \"%2\")");
|
||||||
|
message = message.arg(config->displayName()).arg(config->runConfigDisplayName());
|
||||||
|
emit testResultReady(
|
||||||
|
TestResultPtr(new FaultyTestResult(Result::MessageWarn, message)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
|
||||||
|
tr("Project is null for \"%1\". Removing from test run.\n"
|
||||||
|
"Check the test environment.").arg(config->displayName()))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return testCaseCount;
|
||||||
|
}
|
||||||
|
|
||||||
void TestRunner::runTests()
|
void TestRunner::runTests()
|
||||||
{
|
{
|
||||||
QList<TestConfiguration *> toBeRemoved;
|
QList<TestConfiguration *> toBeRemoved;
|
||||||
@@ -381,10 +408,17 @@ void TestRunner::runTests()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QFuture<TestResultPtr> future = Utils::runAsync(&performTestRun, m_selectedTests,
|
int testCaseCount = precheckTestConfigurations();
|
||||||
*AutotestPlugin::settings());
|
|
||||||
|
// Fake future interface - destruction will be handled by QFuture/QFutureWatcher
|
||||||
|
m_fakeFutureInterface = new QFutureInterface<TestResultPtr>(QFutureInterfaceBase::Running);
|
||||||
|
QFuture<TestResultPtr> future = m_fakeFutureInterface->future();
|
||||||
|
m_fakeFutureInterface->setProgressRange(0, testCaseCount);
|
||||||
|
m_fakeFutureInterface->setProgressValue(0);
|
||||||
m_futureWatcher.setFuture(future);
|
m_futureWatcher.setFuture(future);
|
||||||
|
|
||||||
Core::ProgressManager::addTask(future, tr("Running Tests"), Autotest::Constants::TASK_INDEX);
|
Core::ProgressManager::addTask(future, tr("Running Tests"), Autotest::Constants::TASK_INDEX);
|
||||||
|
scheduleNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void processOutput(TestOutputReader *outputreader, const QString &msg,
|
static void processOutput(TestOutputReader *outputreader, const QString &msg,
|
||||||
@@ -552,6 +586,11 @@ void TestRunner::buildFinished(bool success)
|
|||||||
|
|
||||||
void TestRunner::onFinished()
|
void TestRunner::onFinished()
|
||||||
{
|
{
|
||||||
|
// if we've been canceled and we still have test configurations queued just throw them away
|
||||||
|
qDeleteAll(m_selectedTests);
|
||||||
|
m_selectedTests.clear();
|
||||||
|
|
||||||
|
m_fakeFutureInterface = nullptr;
|
||||||
m_executingTests = false;
|
m_executingTests = false;
|
||||||
emit testRunFinished();
|
emit testRunFinished();
|
||||||
}
|
}
|
||||||
|
@@ -31,12 +31,13 @@
|
|||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QFutureWatcher>
|
#include <QFutureWatcher>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QProcess>
|
#include <QQueue>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QComboBox;
|
class QComboBox;
|
||||||
class QDialogButtonBox;
|
class QDialogButtonBox;
|
||||||
class QLabel;
|
class QLabel;
|
||||||
|
class QProcess;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
@@ -51,6 +52,8 @@ class TestRunner : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum CancelReason { UserCanceled, Timeout };
|
||||||
|
|
||||||
static TestRunner* instance();
|
static TestRunner* instance();
|
||||||
~TestRunner();
|
~TestRunner();
|
||||||
|
|
||||||
@@ -71,14 +74,24 @@ private:
|
|||||||
void buildFinished(bool success);
|
void buildFinished(bool success);
|
||||||
void onFinished();
|
void onFinished();
|
||||||
|
|
||||||
|
int precheckTestConfigurations();
|
||||||
|
void scheduleNext();
|
||||||
|
void cancelCurrent(CancelReason reason);
|
||||||
|
void onProcessFinished();
|
||||||
|
void resetInternalPointers();
|
||||||
|
|
||||||
void runTests();
|
void runTests();
|
||||||
void debugTests();
|
void debugTests();
|
||||||
void runOrDebugTests();
|
void runOrDebugTests();
|
||||||
explicit TestRunner(QObject *parent = 0);
|
explicit TestRunner(QObject *parent = 0);
|
||||||
|
|
||||||
QFutureWatcher<TestResultPtr> m_futureWatcher;
|
QFutureWatcher<TestResultPtr> m_futureWatcher;
|
||||||
QList<TestConfiguration *> m_selectedTests;
|
QFutureInterface<TestResultPtr> *m_fakeFutureInterface = nullptr;
|
||||||
bool m_executingTests;
|
QQueue<TestConfiguration *> m_selectedTests;
|
||||||
|
bool m_executingTests = false;
|
||||||
|
TestConfiguration *m_currentConfig = nullptr;
|
||||||
|
QProcess *m_currentProcess = nullptr;
|
||||||
|
TestOutputReader *m_currentOutputReader = nullptr;
|
||||||
TestRunMode m_runMode = TestRunMode::Run;
|
TestRunMode m_runMode = TestRunMode::Run;
|
||||||
|
|
||||||
// temporarily used if building before running is necessary
|
// temporarily used if building before running is necessary
|
||||||
|
@@ -83,8 +83,8 @@ ClangTextMark::ClangTextMark(const FileName &fileName,
|
|||||||
updateIcon();
|
updateIcon();
|
||||||
if (fullVisualization) {
|
if (fullVisualization) {
|
||||||
setLineAnnotation(Utils::diagnosticCategoryPrefixRemoved(diagnostic.text.toString()));
|
setLineAnnotation(Utils::diagnosticCategoryPrefixRemoved(diagnostic.text.toString()));
|
||||||
setColor(warning ? ::Utils::Theme::ClangCodeModel_Warning_TextMarkColor
|
setColor(warning ? ::Utils::Theme::CodeModel_Warning_TextMarkColor
|
||||||
: ::Utils::Theme::ClangCodeModel_Error_TextMarkColor);
|
: ::Utils::Theme::CodeModel_Error_TextMarkColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -161,6 +161,10 @@ ClangTidyClazyTool::ClangTidyClazyTool()
|
|||||||
// Apply fixits button
|
// Apply fixits button
|
||||||
m_applyFixitsButton = new QToolButton;
|
m_applyFixitsButton = new QToolButton;
|
||||||
m_applyFixitsButton->setText(tr("Apply Fixits"));
|
m_applyFixitsButton->setText(tr("Apply Fixits"));
|
||||||
|
m_applyFixitsButton->setEnabled(false);
|
||||||
|
connect(m_diagnosticModel,
|
||||||
|
&ClangToolsDiagnosticModel::fixItsToApplyCountChanged,
|
||||||
|
[this](int c) { m_applyFixitsButton->setEnabled(c); });
|
||||||
connect(m_applyFixitsButton, &QToolButton::clicked, [this]() {
|
connect(m_applyFixitsButton, &QToolButton::clicked, [this]() {
|
||||||
QVector<Diagnostic> diagnosticsWithFixits;
|
QVector<Diagnostic> diagnosticsWithFixits;
|
||||||
|
|
||||||
|
@@ -6,6 +6,7 @@ QtcPlugin {
|
|||||||
|
|
||||||
Depends { name: "Debugger" }
|
Depends { name: "Debugger" }
|
||||||
Depends { name: "Core" }
|
Depends { name: "Core" }
|
||||||
|
Depends { name: "TextEditor" }
|
||||||
Depends { name: "CppTools" }
|
Depends { name: "CppTools" }
|
||||||
Depends { name: "ExtensionSystem" }
|
Depends { name: "ExtensionSystem" }
|
||||||
Depends { name: "ProjectExplorer" }
|
Depends { name: "ProjectExplorer" }
|
||||||
|
@@ -34,7 +34,6 @@
|
|||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/utilsicons.h>
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@@ -61,8 +60,13 @@ ClangToolsDiagnosticModel::ClangToolsDiagnosticModel(QObject *parent)
|
|||||||
|
|
||||||
void ClangToolsDiagnosticModel::addDiagnostics(const QList<Diagnostic> &diagnostics)
|
void ClangToolsDiagnosticModel::addDiagnostics(const QList<Diagnostic> &diagnostics)
|
||||||
{
|
{
|
||||||
foreach (const Diagnostic &d, diagnostics)
|
const auto onFixItChanged = [this](bool checked){
|
||||||
rootItem()->appendChild(new DiagnosticItem(d));
|
m_fixItsToApplyCount += checked ? +1 : -1;
|
||||||
|
emit fixItsToApplyCountChanged(m_fixItsToApplyCount);
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const Diagnostic &d : diagnostics)
|
||||||
|
rootItem()->appendChild(new DiagnosticItem(d, onFixItChanged));
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<Diagnostic> ClangToolsDiagnosticModel::diagnostics() const
|
QList<Diagnostic> ClangToolsDiagnosticModel::diagnostics() const
|
||||||
@@ -199,7 +203,9 @@ static QString fullText(const Diagnostic &diagnostic)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DiagnosticItem::DiagnosticItem(const Diagnostic &diag) : m_diagnostic(diag)
|
DiagnosticItem::DiagnosticItem(const Diagnostic &diag, const OnCheckedFixit &onCheckedFixit)
|
||||||
|
: m_diagnostic(diag)
|
||||||
|
, m_onCheckedFixit(onCheckedFixit)
|
||||||
{
|
{
|
||||||
// Don't show explaining steps if they add no information.
|
// Don't show explaining steps if they add no information.
|
||||||
if (diag.explainingSteps.count() == 1) {
|
if (diag.explainingSteps.count() == 1) {
|
||||||
@@ -214,21 +220,15 @@ DiagnosticItem::DiagnosticItem(const Diagnostic &diag) : m_diagnostic(diag)
|
|||||||
|
|
||||||
Qt::ItemFlags DiagnosticItem::flags(int column) const
|
Qt::ItemFlags DiagnosticItem::flags(int column) const
|
||||||
{
|
{
|
||||||
if (column == DiagnosticView::FixItColumn && m_diagnostic.hasFixits)
|
const Qt::ItemFlags itemFlags = TreeItem::flags(column);
|
||||||
return TreeItem::flags(column) | Qt::ItemIsUserCheckable;
|
if (column == DiagnosticView::FixItColumn) {
|
||||||
return TreeItem::flags(column);
|
if (m_diagnostic.hasFixits)
|
||||||
}
|
return itemFlags | Qt::ItemIsUserCheckable;
|
||||||
|
else
|
||||||
static QVariant locationData(int role, const Debugger::DiagnosticLocation &location)
|
return itemFlags & ~Qt::ItemIsEnabled;
|
||||||
{
|
|
||||||
switch (role) {
|
|
||||||
case Debugger::DetailedErrorView::LocationRole:
|
|
||||||
return QVariant::fromValue(location);
|
|
||||||
case Qt::ToolTipRole:
|
|
||||||
return location.filePath.isEmpty() ? QVariant() : QVariant(location.filePath);
|
|
||||||
default:
|
|
||||||
return QVariant();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return itemFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QVariant iconData(const QString &type)
|
static QVariant iconData(const QString &type)
|
||||||
@@ -247,7 +247,7 @@ static QVariant iconData(const QString &type)
|
|||||||
QVariant DiagnosticItem::data(int column, int role) const
|
QVariant DiagnosticItem::data(int column, int role) const
|
||||||
{
|
{
|
||||||
if (column == Debugger::DetailedErrorView::LocationColumn)
|
if (column == Debugger::DetailedErrorView::LocationColumn)
|
||||||
return locationData(role, m_diagnostic.location);
|
return Debugger::DetailedErrorView::locationData(role, m_diagnostic.location);
|
||||||
|
|
||||||
if (column == DiagnosticView::FixItColumn) {
|
if (column == DiagnosticView::FixItColumn) {
|
||||||
if (role == Qt::CheckStateRole)
|
if (role == Qt::CheckStateRole)
|
||||||
@@ -277,6 +277,8 @@ bool DiagnosticItem::setData(int column, const QVariant &data, int role)
|
|||||||
if (column == DiagnosticView::FixItColumn && role == Qt::CheckStateRole) {
|
if (column == DiagnosticView::FixItColumn && role == Qt::CheckStateRole) {
|
||||||
m_applyFixits = data.value<Qt::CheckState>() == Qt::Checked ? true : false;
|
m_applyFixits = data.value<Qt::CheckState>() == Qt::Checked ? true : false;
|
||||||
update();
|
update();
|
||||||
|
if (m_onCheckedFixit)
|
||||||
|
m_onCheckedFixit(m_applyFixits);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,7 +292,7 @@ ExplainingStepItem::ExplainingStepItem(const ExplainingStep &step) : m_step(step
|
|||||||
QVariant ExplainingStepItem::data(int column, int role) const
|
QVariant ExplainingStepItem::data(int column, int role) const
|
||||||
{
|
{
|
||||||
if (column == Debugger::DetailedErrorView::LocationColumn)
|
if (column == Debugger::DetailedErrorView::LocationColumn)
|
||||||
return locationData(role, m_step.location);
|
return Debugger::DetailedErrorView::locationData(role, m_step.location);
|
||||||
|
|
||||||
if (column == DiagnosticView::FixItColumn)
|
if (column == DiagnosticView::FixItColumn)
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
@@ -35,6 +35,8 @@
|
|||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace ProjectExplorer { class Project; }
|
namespace ProjectExplorer { class Project; }
|
||||||
|
|
||||||
namespace ClangTools {
|
namespace ClangTools {
|
||||||
@@ -43,7 +45,8 @@ namespace Internal {
|
|||||||
class DiagnosticItem : public Utils::TreeItem
|
class DiagnosticItem : public Utils::TreeItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DiagnosticItem(const Diagnostic &diag);
|
using OnCheckedFixit = std::function<void(bool)>;
|
||||||
|
DiagnosticItem(const Diagnostic &diag, const OnCheckedFixit &onCheckedFixit);
|
||||||
|
|
||||||
Diagnostic diagnostic() const { return m_diagnostic; }
|
Diagnostic diagnostic() const { return m_diagnostic; }
|
||||||
bool applyFixits() const { return m_applyFixits; }
|
bool applyFixits() const { return m_applyFixits; }
|
||||||
@@ -56,6 +59,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
const Diagnostic m_diagnostic;
|
const Diagnostic m_diagnostic;
|
||||||
bool m_applyFixits = false;
|
bool m_applyFixits = false;
|
||||||
|
OnCheckedFixit m_onCheckedFixit;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ClangToolsDiagnosticModel : public Utils::TreeModel<>
|
class ClangToolsDiagnosticModel : public Utils::TreeModel<>
|
||||||
@@ -71,6 +75,12 @@ public:
|
|||||||
enum ItemRole {
|
enum ItemRole {
|
||||||
DiagnosticRole = Debugger::DetailedErrorView::FullTextRole + 1
|
DiagnosticRole = Debugger::DetailedErrorView::FullTextRole + 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void fixItsToApplyCountChanged(int count);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_fixItsToApplyCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DiagnosticFilterModel : public QSortFilterProxyModel
|
class DiagnosticFilterModel : public QSortFilterProxyModel
|
||||||
|
@@ -196,6 +196,12 @@ void BuildDirManager::setParametersAndRequestParse(const BuildDirParameters &par
|
|||||||
int newReaderReparseOptions,
|
int newReaderReparseOptions,
|
||||||
int existingReaderReparseOptions)
|
int existingReaderReparseOptions)
|
||||||
{
|
{
|
||||||
|
if (!parameters.cmakeTool) {
|
||||||
|
TaskHub::addTask(Task::Error,
|
||||||
|
tr("The kit needs to define a CMake tool to parse this project."),
|
||||||
|
ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
|
||||||
|
return;
|
||||||
|
}
|
||||||
QTC_ASSERT(parameters.isValid(), return);
|
QTC_ASSERT(parameters.isValid(), return);
|
||||||
|
|
||||||
if (m_reader)
|
if (m_reader)
|
||||||
|
@@ -279,8 +279,7 @@ static std::vector<std::unique_ptr<FileNode>> &&
|
|||||||
removeKnownNodes(const QSet<Utils::FileName> &knownFiles,
|
removeKnownNodes(const QSet<Utils::FileName> &knownFiles,
|
||||||
std::vector<std::unique_ptr<FileNode>> &&files)
|
std::vector<std::unique_ptr<FileNode>> &&files)
|
||||||
{
|
{
|
||||||
std::remove_if(std::begin(files), std::end(files),
|
Utils::erase(files, [&knownFiles](const std::unique_ptr<FileNode> &n) {
|
||||||
[&knownFiles](const std::unique_ptr<FileNode> &n) {
|
|
||||||
return knownFiles.contains(n->filePath());
|
return knownFiles.contains(n->filePath());
|
||||||
});
|
});
|
||||||
return std::move(files);
|
return std::move(files);
|
||||||
|
@@ -19,6 +19,108 @@
|
|||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
|
<widget class="QWidget" name="tab_2">
|
||||||
|
<attribute name="title">
|
||||||
|
<string notr="true">&Project Parts</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_12">
|
||||||
|
<item>
|
||||||
|
<widget class="QSplitter" name="projectPartsSplitter">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="QTabWidget" name="projectPartTab">
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="tab_17">
|
||||||
|
<attribute name="title">
|
||||||
|
<string notr="true">&General</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||||
|
<item>
|
||||||
|
<widget class="QTreeView" name="partGeneralView"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_13">
|
||||||
|
<attribute name="title">
|
||||||
|
<string notr="true">Project &Files</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_14">
|
||||||
|
<item>
|
||||||
|
<widget class="QTreeView" name="projectFilesView"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_14">
|
||||||
|
<attribute name="title">
|
||||||
|
<string notr="true">&Defines</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_19">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string notr="true">Toolchain Defines</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||||
|
<item>
|
||||||
|
<widget class="QPlainTextEdit" name="partToolchainDefinesEdit">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
|
<property name="title">
|
||||||
|
<string notr="true">Project Defines</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_15">
|
||||||
|
<item>
|
||||||
|
<widget class="QPlainTextEdit" name="partProjectDefinesEdit">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_15">
|
||||||
|
<attribute name="title">
|
||||||
|
<string notr="true">&Header Paths</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_16">
|
||||||
|
<item>
|
||||||
|
<widget class="QTreeView" name="projectHeaderPathsView"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_16">
|
||||||
|
<attribute name="title">
|
||||||
|
<string notr="true">Pre&compiled Headers</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_18">
|
||||||
|
<item>
|
||||||
|
<widget class="QPlainTextEdit" name="partPrecompiledHeadersEdit">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
<widget class="QWidget" name="tab">
|
<widget class="QWidget" name="tab">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string notr="true">&Snapshots and Documents</string>
|
<string notr="true">&Snapshots and Documents</string>
|
||||||
@@ -182,108 +284,6 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="tab_2">
|
|
||||||
<attribute name="title">
|
|
||||||
<string notr="true">&Project Parts</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_12">
|
|
||||||
<item>
|
|
||||||
<widget class="QSplitter" name="projectPartsSplitter">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<widget class="QTabWidget" name="projectPartTab">
|
|
||||||
<property name="currentIndex">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="tab_17">
|
|
||||||
<attribute name="title">
|
|
||||||
<string notr="true">&General</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
|
||||||
<item>
|
|
||||||
<widget class="QTreeView" name="partGeneralView"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="tab_13">
|
|
||||||
<attribute name="title">
|
|
||||||
<string notr="true">Project &Files</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_14">
|
|
||||||
<item>
|
|
||||||
<widget class="QTreeView" name="projectFilesView"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="tab_14">
|
|
||||||
<attribute name="title">
|
|
||||||
<string notr="true">&Defines</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_19">
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="groupBox">
|
|
||||||
<property name="title">
|
|
||||||
<string notr="true">Toolchain Defines</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
|
||||||
<item>
|
|
||||||
<widget class="QPlainTextEdit" name="partToolchainDefinesEdit">
|
|
||||||
<property name="readOnly">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="groupBox_2">
|
|
||||||
<property name="title">
|
|
||||||
<string notr="true">Project Defines</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_15">
|
|
||||||
<item>
|
|
||||||
<widget class="QPlainTextEdit" name="partProjectDefinesEdit">
|
|
||||||
<property name="readOnly">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="tab_15">
|
|
||||||
<attribute name="title">
|
|
||||||
<string notr="true">&Header Paths</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_16">
|
|
||||||
<item>
|
|
||||||
<widget class="QTreeView" name="projectHeaderPathsView"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="tab_16">
|
|
||||||
<attribute name="title">
|
|
||||||
<string notr="true">Pre&compiled Headers</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_18">
|
|
||||||
<item>
|
|
||||||
<widget class="QPlainTextEdit" name="partPrecompiledHeadersEdit">
|
|
||||||
<property name="readOnly">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="tab_3">
|
<widget class="QWidget" name="tab_3">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string notr="true">&Working Copy</string>
|
<string notr="true">&Working Copy</string>
|
||||||
|
@@ -41,91 +41,14 @@
|
|||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QSharedPointer>
|
|
||||||
#include <QTextDocument>
|
|
||||||
|
|
||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class DetailedErrorDelegate : public QStyledItemDelegate
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
DetailedErrorDelegate(QTreeView *parent) : QStyledItemDelegate(parent) { }
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString actualText(const QModelIndex &index) const
|
|
||||||
{
|
|
||||||
const auto location = index.model()->data(index, DetailedErrorView::LocationRole)
|
|
||||||
.value<DiagnosticLocation>();
|
|
||||||
return location.isValid()
|
|
||||||
? QString::fromLatin1("<a href=\"file://%1\">%2:%3:%4")
|
|
||||||
.arg(location.filePath, QFileInfo(location.filePath).fileName())
|
|
||||||
.arg(location.line)
|
|
||||||
.arg(location.column)
|
|
||||||
: QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
using DocConstPtr = QSharedPointer<const QTextDocument>;
|
|
||||||
DocConstPtr document(const QStyleOptionViewItem &option) const
|
|
||||||
{
|
|
||||||
const auto doc = QSharedPointer<QTextDocument>::create();
|
|
||||||
doc->setHtml(option.text);
|
|
||||||
doc->setTextWidth(option.rect.width());
|
|
||||||
doc->setDocumentMargin(0);
|
|
||||||
return doc;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
|
|
||||||
{
|
|
||||||
QStyleOptionViewItem opt = option;
|
|
||||||
opt.text = actualText(index);
|
|
||||||
initStyleOption(&opt, index);
|
|
||||||
|
|
||||||
const DocConstPtr doc = document(opt);
|
|
||||||
return QSize(doc->idealWidth(), doc->size().height());
|
|
||||||
}
|
|
||||||
|
|
||||||
void paint(QPainter *painter, const QStyleOptionViewItem &option,
|
|
||||||
const QModelIndex &index) const override
|
|
||||||
{
|
|
||||||
QStyleOptionViewItem opt = option;
|
|
||||||
initStyleOption(&opt, index);
|
|
||||||
|
|
||||||
QStyle *style = opt.widget? opt.widget->style() : QApplication::style();
|
|
||||||
|
|
||||||
// Painting item without text
|
|
||||||
opt.text.clear();
|
|
||||||
style->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
|
|
||||||
opt.text = actualText(index);
|
|
||||||
|
|
||||||
QAbstractTextDocumentLayout::PaintContext ctx;
|
|
||||||
|
|
||||||
// Highlighting text if item is selected
|
|
||||||
if (opt.state & QStyle::State_Selected) {
|
|
||||||
ctx.palette.setColor(QPalette::Text, opt.palette.color(QPalette::Active,
|
|
||||||
QPalette::HighlightedText));
|
|
||||||
}
|
|
||||||
|
|
||||||
QRect textRect = style->subElementRect(QStyle::SE_ItemViewItemText, &opt);
|
|
||||||
painter->save();
|
|
||||||
painter->translate(textRect.topLeft());
|
|
||||||
painter->setClipRect(textRect.translated(-textRect.topLeft()));
|
|
||||||
document(opt)->documentLayout()->draw(painter, ctx);
|
|
||||||
painter->restore();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
|
|
||||||
|
|
||||||
DetailedErrorView::DetailedErrorView(QWidget *parent) :
|
DetailedErrorView::DetailedErrorView(QWidget *parent) :
|
||||||
QTreeView(parent),
|
QTreeView(parent),
|
||||||
m_copyAction(new QAction(this))
|
m_copyAction(new QAction(this))
|
||||||
{
|
{
|
||||||
header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||||
setItemDelegateForColumn(LocationColumn, new Internal::DetailedErrorDelegate(this));
|
|
||||||
|
|
||||||
m_copyAction->setText(tr("Copy"));
|
m_copyAction->setText(tr("Copy"));
|
||||||
m_copyAction->setIcon(Utils::Icons::COPY.icon());
|
m_copyAction->setIcon(Utils::Icons::COPY.icon());
|
||||||
@@ -187,6 +110,31 @@ void DetailedErrorView::goBack()
|
|||||||
setCurrentRow(prevRow >= 0 ? prevRow : rowCount() - 1);
|
setCurrentRow(prevRow >= 0 ? prevRow : rowCount() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariant DetailedErrorView::locationData(int role, const DiagnosticLocation &location)
|
||||||
|
{
|
||||||
|
switch (role) {
|
||||||
|
case Debugger::DetailedErrorView::LocationRole:
|
||||||
|
return QVariant::fromValue(location);
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
return location.isValid() ? QString::fromLatin1("%1:%2:%3")
|
||||||
|
.arg(QFileInfo(location.filePath).fileName())
|
||||||
|
.arg(location.line)
|
||||||
|
.arg(location.column)
|
||||||
|
: QString();
|
||||||
|
case Qt::ToolTipRole:
|
||||||
|
return location.filePath.isEmpty() ? QVariant() : QVariant(location.filePath);
|
||||||
|
case Qt::FontRole: {
|
||||||
|
QFont font = QApplication::font();
|
||||||
|
font.setUnderline(true);
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
case Qt::ForegroundRole:
|
||||||
|
return QApplication::palette().link().color();
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int DetailedErrorView::rowCount() const
|
int DetailedErrorView::rowCount() const
|
||||||
{
|
{
|
||||||
return model() ? model()->rowCount() : 0;
|
return model() ? model()->rowCount() : 0;
|
||||||
@@ -218,5 +166,3 @@ void DetailedErrorView::setCurrentRow(int row)
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Debugger
|
} // namespace Debugger
|
||||||
|
|
||||||
#include "detailederrorview.moc"
|
|
||||||
|
@@ -32,6 +32,8 @@
|
|||||||
|
|
||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
|
|
||||||
|
class DiagnosticLocation;
|
||||||
|
|
||||||
class DEBUGGER_EXPORT DetailedErrorView : public QTreeView
|
class DEBUGGER_EXPORT DetailedErrorView : public QTreeView
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -53,6 +55,8 @@ public:
|
|||||||
LocationColumn,
|
LocationColumn,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static QVariant locationData(int role, const DiagnosticLocation &location);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void contextMenuEvent(QContextMenuEvent *e) override;
|
void contextMenuEvent(QContextMenuEvent *e) override;
|
||||||
void currentChanged(const QModelIndex ¤t, const QModelIndex &previous) override;
|
void currentChanged(const QModelIndex ¤t, const QModelIndex &previous) override;
|
||||||
|
@@ -179,6 +179,7 @@ SideDiffEditorWidget::SideDiffEditorWidget(QWidget *parent)
|
|||||||
connect(documentLayout, &TextDocumentLayout::foldChanged,
|
connect(documentLayout, &TextDocumentLayout::foldChanged,
|
||||||
this, &SideDiffEditorWidget::foldChanged);
|
this, &SideDiffEditorWidget::foldChanged);
|
||||||
setCodeFoldingSupported(true);
|
setCodeFoldingSupported(true);
|
||||||
|
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SideDiffEditorWidget::saveState()
|
void SideDiffEditorWidget::saveState()
|
||||||
@@ -714,6 +715,13 @@ SideBySideDiffEditorWidget::SideBySideDiffEditorWidget(QWidget *parent)
|
|||||||
connect(m_rightEditor, &SideDiffEditorWidget::foldChanged,
|
connect(m_rightEditor, &SideDiffEditorWidget::foldChanged,
|
||||||
m_leftEditor, &SideDiffEditorWidget::setFolded);
|
m_leftEditor, &SideDiffEditorWidget::setFolded);
|
||||||
|
|
||||||
|
connect(m_leftEditor->horizontalScrollBar(), &QAbstractSlider::rangeChanged,
|
||||||
|
this, &SideBySideDiffEditorWidget::syncHorizontalScrollBarPolicy);
|
||||||
|
|
||||||
|
connect(m_rightEditor->horizontalScrollBar(), &QAbstractSlider::rangeChanged,
|
||||||
|
this, &SideBySideDiffEditorWidget::syncHorizontalScrollBarPolicy);
|
||||||
|
|
||||||
|
syncHorizontalScrollBarPolicy();
|
||||||
|
|
||||||
m_splitter = new MiniSplitter(this);
|
m_splitter = new MiniSplitter(this);
|
||||||
m_splitter->addWidget(m_leftEditor);
|
m_splitter->addWidget(m_leftEditor);
|
||||||
@@ -1133,6 +1141,18 @@ void SideBySideDiffEditorWidget::rightCursorPositionChanged()
|
|||||||
rightHSliderChanged();
|
rightHSliderChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SideBySideDiffEditorWidget::syncHorizontalScrollBarPolicy()
|
||||||
|
{
|
||||||
|
const bool alwaysOn = m_leftEditor->horizontalScrollBar()->maximum()
|
||||||
|
|| m_rightEditor->horizontalScrollBar()->maximum();
|
||||||
|
const Qt::ScrollBarPolicy newPolicy = alwaysOn
|
||||||
|
? Qt::ScrollBarAlwaysOn : Qt::ScrollBarAsNeeded;
|
||||||
|
if (m_leftEditor->horizontalScrollBarPolicy() != newPolicy)
|
||||||
|
m_leftEditor->setHorizontalScrollBarPolicy(newPolicy);
|
||||||
|
if (m_rightEditor->horizontalScrollBarPolicy() != newPolicy)
|
||||||
|
m_rightEditor->setHorizontalScrollBarPolicy(newPolicy);
|
||||||
|
}
|
||||||
|
|
||||||
void SideBySideDiffEditorWidget::handlePositionChange(SideDiffEditorWidget *source, SideDiffEditorWidget *dest)
|
void SideBySideDiffEditorWidget::handlePositionChange(SideDiffEditorWidget *source, SideDiffEditorWidget *dest)
|
||||||
{
|
{
|
||||||
if (m_controller.m_ignoreCurrentIndexChange)
|
if (m_controller.m_ignoreCurrentIndexChange)
|
||||||
|
@@ -95,6 +95,7 @@ private:
|
|||||||
void rightHSliderChanged();
|
void rightHSliderChanged();
|
||||||
void leftCursorPositionChanged();
|
void leftCursorPositionChanged();
|
||||||
void rightCursorPositionChanged();
|
void rightCursorPositionChanged();
|
||||||
|
void syncHorizontalScrollBarPolicy();
|
||||||
void handlePositionChange(SideDiffEditorWidget *source, SideDiffEditorWidget *dest);
|
void handlePositionChange(SideDiffEditorWidget *source, SideDiffEditorWidget *dest);
|
||||||
void syncCursor(SideDiffEditorWidget *source, SideDiffEditorWidget *dest);
|
void syncCursor(SideDiffEditorWidget *source, SideDiffEditorWidget *dest);
|
||||||
|
|
||||||
|
@@ -337,22 +337,4 @@ BuildStep *BuildStepFactory::restore(BuildStepList *parent, const QVariantMap &m
|
|||||||
return bs;
|
return bs;
|
||||||
}
|
}
|
||||||
|
|
||||||
BuildStep *BuildStepFactory::clone(BuildStepList *parent, BuildStep *product)
|
|
||||||
{
|
|
||||||
if ((m_info.flags & BuildStepInfo::Unclonable) != 0)
|
|
||||||
return nullptr;
|
|
||||||
if (m_info.id != product->id())
|
|
||||||
return nullptr;
|
|
||||||
BuildStep *bs = m_info.creator(parent);
|
|
||||||
if (!bs)
|
|
||||||
return nullptr;
|
|
||||||
const QVariantMap map = product->toMap();
|
|
||||||
if (!bs->fromMap(map)) {
|
|
||||||
QTC_CHECK(false);
|
|
||||||
delete bs;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return bs;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // ProjectExplorer
|
} // ProjectExplorer
|
||||||
|
@@ -132,7 +132,6 @@ public:
|
|||||||
Core::Id stepId() const;
|
Core::Id stepId() const;
|
||||||
BuildStep *create(BuildStepList *parent, Core::Id id);
|
BuildStep *create(BuildStepList *parent, Core::Id id);
|
||||||
BuildStep *restore(BuildStepList *parent, const QVariantMap &map);
|
BuildStep *restore(BuildStepList *parent, const QVariantMap &map);
|
||||||
BuildStep *clone(BuildStepList *parent, BuildStep *product);
|
|
||||||
|
|
||||||
virtual bool canHandle(BuildStepList *bsl) const;
|
virtual bool canHandle(BuildStepList *bsl) const;
|
||||||
|
|
||||||
|
@@ -701,6 +701,11 @@ void Project::createTargetFromMap(const QVariantMap &map, int index)
|
|||||||
Target *t = restoreTarget(targetMap);
|
Target *t = restoreTarget(targetMap);
|
||||||
if (!t)
|
if (!t)
|
||||||
return;
|
return;
|
||||||
|
if (t->runConfigurations().isEmpty() && t->buildConfigurations().isEmpty()) {
|
||||||
|
delete t;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
addTarget(t);
|
addTarget(t);
|
||||||
}
|
}
|
||||||
|
@@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include <coreplugin/messagebox.h>
|
#include <coreplugin/messagebox.h>
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QQmlContext>
|
#include <QQmlContext>
|
||||||
|
|
||||||
@@ -135,15 +136,13 @@ QStringList PropertyEditorContextObject::autoComplete(const QString &text, int p
|
|||||||
|
|
||||||
void PropertyEditorContextObject::toogleExportAlias()
|
void PropertyEditorContextObject::toogleExportAlias()
|
||||||
{
|
{
|
||||||
if (!m_model || !m_model->rewriterView())
|
QTC_ASSERT(m_model && m_model->rewriterView(), return);
|
||||||
return;
|
|
||||||
|
|
||||||
/* Ideally we should not missuse the rewriterView
|
/* Ideally we should not missuse the rewriterView
|
||||||
* If we add more code here we have to forward the property editor view */
|
* If we add more code here we have to forward the property editor view */
|
||||||
RewriterView *rewriterView = m_model->rewriterView();
|
RewriterView *rewriterView = m_model->rewriterView();
|
||||||
|
|
||||||
if (rewriterView->selectedModelNodes().isEmpty())
|
QTC_ASSERT(!rewriterView->selectedModelNodes().isEmpty(), return);
|
||||||
return;
|
|
||||||
|
|
||||||
const ModelNode selectedNode = rewriterView->selectedModelNodes().constFirst();
|
const ModelNode selectedNode = rewriterView->selectedModelNodes().constFirst();
|
||||||
|
|
||||||
@@ -174,15 +173,13 @@ void PropertyEditorContextObject::toogleExportAlias()
|
|||||||
void PropertyEditorContextObject::changeTypeName(const QString &typeName)
|
void PropertyEditorContextObject::changeTypeName(const QString &typeName)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!m_model || !m_model->rewriterView())
|
QTC_ASSERT(m_model && m_model->rewriterView(), return);
|
||||||
return;
|
|
||||||
|
|
||||||
/* Ideally we should not missuse the rewriterView
|
/* Ideally we should not missuse the rewriterView
|
||||||
* If we add more code here we have to forward the property editor view */
|
* If we add more code here we have to forward the property editor view */
|
||||||
RewriterView *rewriterView = m_model->rewriterView();
|
RewriterView *rewriterView = m_model->rewriterView();
|
||||||
|
|
||||||
if (rewriterView->selectedModelNodes().isEmpty())
|
QTC_ASSERT(!rewriterView->selectedModelNodes().isEmpty(), return);
|
||||||
return;
|
|
||||||
|
|
||||||
ModelNode selectedNode = rewriterView->selectedModelNodes().constFirst();
|
ModelNode selectedNode = rewriterView->selectedModelNodes().constFirst();
|
||||||
|
|
||||||
@@ -210,15 +207,13 @@ void PropertyEditorContextObject::changeTypeName(const QString &typeName)
|
|||||||
|
|
||||||
void PropertyEditorContextObject::insertKeyframe(const QString &propertyName)
|
void PropertyEditorContextObject::insertKeyframe(const QString &propertyName)
|
||||||
{
|
{
|
||||||
if (!m_model || !m_model->rewriterView())
|
QTC_ASSERT(m_model && m_model->rewriterView(), return);
|
||||||
return;
|
|
||||||
|
|
||||||
/* Ideally we should not missuse the rewriterView
|
/* Ideally we should not missuse the rewriterView
|
||||||
* If we add more code here we have to forward the property editor view */
|
* If we add more code here we have to forward the property editor view */
|
||||||
RewriterView *rewriterView = m_model->rewriterView();
|
RewriterView *rewriterView = m_model->rewriterView();
|
||||||
|
|
||||||
if (rewriterView->selectedModelNodes().isEmpty())
|
QTC_ASSERT(!rewriterView->selectedModelNodes().isEmpty(), return);
|
||||||
return;
|
|
||||||
|
|
||||||
ModelNode selectedNode = rewriterView->selectedModelNodes().constFirst();
|
ModelNode selectedNode = rewriterView->selectedModelNodes().constFirst();
|
||||||
|
|
||||||
|
@@ -271,6 +271,8 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q
|
|||||||
|
|
||||||
if (qmlObjectNode.isValid()) {
|
if (qmlObjectNode.isValid()) {
|
||||||
|
|
||||||
|
m_contextObject->setModel(propertyEditor->model());
|
||||||
|
|
||||||
qCInfo(propertyEditorBenchmark) << Q_FUNC_INFO;
|
qCInfo(propertyEditorBenchmark) << Q_FUNC_INFO;
|
||||||
|
|
||||||
QTime time;
|
QTime time;
|
||||||
|
@@ -90,8 +90,8 @@ void QmlJSTextMark::init(bool warning, const QString message)
|
|||||||
{
|
{
|
||||||
setIcon(warning ? Utils::Icons::CODEMODEL_WARNING.icon()
|
setIcon(warning ? Utils::Icons::CODEMODEL_WARNING.icon()
|
||||||
: Utils::Icons::CODEMODEL_ERROR.icon());
|
: Utils::Icons::CODEMODEL_ERROR.icon());
|
||||||
setColor(warning ? Utils::Theme::ClangCodeModel_Warning_TextMarkColor
|
setColor(warning ? Utils::Theme::CodeModel_Warning_TextMarkColor
|
||||||
: Utils::Theme::ClangCodeModel_Error_TextMarkColor);
|
: Utils::Theme::CodeModel_Error_TextMarkColor);
|
||||||
setDefaultToolTip(warning ? QApplication::translate("QmlJS Code Model Marks", "Code Model Warning")
|
setDefaultToolTip(warning ? QApplication::translate("QmlJS Code Model Marks", "Code Model Warning")
|
||||||
: QApplication::translate("QmlJS Code Model Marks", "Code Model Error"));
|
: QApplication::translate("QmlJS Code Model Marks", "Code Model Error"));
|
||||||
setToolTip(message);
|
setToolTip(message);
|
||||||
|
@@ -5363,15 +5363,13 @@ void TextEditorWidgetPrivate::updateCurrentLineInScrollbar()
|
|||||||
{
|
{
|
||||||
if (m_highlightCurrentLine && m_highlightScrollBarController) {
|
if (m_highlightCurrentLine && m_highlightScrollBarController) {
|
||||||
m_highlightScrollBarController->removeHighlights(Constants::SCROLL_BAR_CURRENT_LINE);
|
m_highlightScrollBarController->removeHighlights(Constants::SCROLL_BAR_CURRENT_LINE);
|
||||||
if (m_highlightScrollBarController->scrollBar()->maximum() > 0) {
|
const QTextCursor &tc = q->textCursor();
|
||||||
const QTextCursor &tc = q->textCursor();
|
if (QTextLayout *layout = tc.block().layout()) {
|
||||||
if (QTextLayout *layout = tc.block().layout()) {
|
const int pos = q->textCursor().block().firstLineNumber() +
|
||||||
const int pos = q->textCursor().block().firstLineNumber() +
|
layout->lineForTextPosition(tc.positionInBlock()).lineNumber();
|
||||||
layout->lineForTextPosition(tc.positionInBlock()).lineNumber();
|
m_highlightScrollBarController->addHighlight({Constants::SCROLL_BAR_CURRENT_LINE, pos,
|
||||||
m_highlightScrollBarController->addHighlight({Constants::SCROLL_BAR_CURRENT_LINE, pos,
|
Theme::TextEditor_CurrentLine_ScrollBarColor,
|
||||||
Theme::TextEditor_CurrentLine_ScrollBarColor,
|
Highlight::HighestPriority});
|
||||||
Highlight::HighestPriority});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -173,24 +173,16 @@ ErrorItem::ErrorItem(const ErrorListModel *model, const Error &error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static QVariant location(const Frame &frame, int role)
|
static QVariant locationData(int role, const Frame &frame)
|
||||||
{
|
{
|
||||||
switch (role) {
|
const Debugger::DiagnosticLocation location(frame.filePath(), frame.line(), 0);
|
||||||
case Debugger::DetailedErrorView::LocationRole:
|
return Debugger::DetailedErrorView::locationData(role, location);
|
||||||
return QVariant::fromValue(Debugger::DiagnosticLocation(frame.filePath(), frame.line(), 0));
|
|
||||||
case Qt::ToolTipRole:
|
|
||||||
return frame.filePath().isEmpty() ? QVariant() : QVariant(frame.filePath());
|
|
||||||
default:
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant ErrorItem::data(int column, int role) const
|
QVariant ErrorItem::data(int column, int role) const
|
||||||
{
|
{
|
||||||
if (column == Debugger::DetailedErrorView::LocationColumn) {
|
if (column == Debugger::DetailedErrorView::LocationColumn)
|
||||||
const Frame frame = m_model->findRelevantFrame(m_error);
|
return locationData(role, m_model->findRelevantFrame(m_error));
|
||||||
return location(frame, role);
|
|
||||||
}
|
|
||||||
|
|
||||||
// DiagnosticColumn
|
// DiagnosticColumn
|
||||||
switch (role) {
|
switch (role) {
|
||||||
@@ -243,7 +235,7 @@ QVariant StackItem::data(int column, int role) const
|
|||||||
{
|
{
|
||||||
const ErrorItem * const errorItem = getErrorItem();
|
const ErrorItem * const errorItem = getErrorItem();
|
||||||
if (column == Debugger::DetailedErrorView::LocationColumn)
|
if (column == Debugger::DetailedErrorView::LocationColumn)
|
||||||
return location(errorItem->modelPrivate()->findRelevantFrame(errorItem->error()), role);
|
return locationData(role, errorItem->modelPrivate()->findRelevantFrame(errorItem->error()));
|
||||||
|
|
||||||
// DiagnosticColumn
|
// DiagnosticColumn
|
||||||
switch (role) {
|
switch (role) {
|
||||||
@@ -271,7 +263,7 @@ FrameItem::FrameItem(const Frame &frame) : m_frame(frame)
|
|||||||
QVariant FrameItem::data(int column, int role) const
|
QVariant FrameItem::data(int column, int role) const
|
||||||
{
|
{
|
||||||
if (column == Debugger::DetailedErrorView::LocationColumn)
|
if (column == Debugger::DetailedErrorView::LocationColumn)
|
||||||
return location(m_frame, role);
|
return locationData(role, m_frame);
|
||||||
|
|
||||||
// DiagnosticColumn
|
// DiagnosticColumn
|
||||||
switch (role) {
|
switch (role) {
|
||||||
|
@@ -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