Merge remote-tracking branch 'origin/4.7'

Change-Id: I00dd929a4ed32af8f1b76cea57a7c49239dafc7c
This commit is contained in:
Eike Ziller
2018-05-22 09:55:58 +02:00
75 changed files with 523 additions and 3815 deletions

View File

@@ -22,7 +22,7 @@ Prerequisites:
* jom
* On Mac OS X: latest Xcode
* 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")
* CMake (only for manual builds of LLVM/Clang)
* 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
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
@@ -233,9 +233,9 @@ GCC 4 binaries. On Ubuntu, you can download the package from
http://apt.llvm.org/ with:
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 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
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
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
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
@@ -285,7 +285,8 @@ we thank the authors who made this possible:
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
@@ -298,7 +299,9 @@ we thank the authors who made this possible:
Distributed under the University of Illinois/NCSA Open Source License (NCSA),
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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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?
}

View File

@@ -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

View File

@@ -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

View File

@@ -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
+}
+}

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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));
+ }
+ }
+}

View File

@@ -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
+

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,7 +1,7 @@
var Environment = require("qbs.Environment")
var File = require("qbs.File")
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")
function readOutput(executable, args)
@@ -36,7 +36,7 @@ function llvmConfig(hostOS, qtcFunctions)
{
var llvmInstallDirFromEnv = Environment.getEnv("LLVM_INSTALL_DIR")
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

View File

@@ -56,8 +56,8 @@ Module {
})
property stringList llvmToolingCxxFlags: clangProbe.llvmToolingCxxFlags
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: {
if (!clangProbe.found) {

View File

@@ -65,7 +65,7 @@ Controls.TextField {
}
ExtendedFunctionButton {
x: 2
x: 4
anchors.verticalCenter: parent.verticalCenter
backendValue: lineEdit.backendValue
visible: lineEdit.enabled && showExtendedFunctionButton
@@ -127,7 +127,7 @@ Controls.TextField {
padding.top: 2
padding.bottom: 2
padding.left: 16
padding.left: 18
padding.right: lineEdit.showTranslateCheckBox ? 16 : 1
background: Rectangle {
implicitWidth: 100

View File

@@ -33,8 +33,10 @@ Controls.SpinBox {
property color textColor: colorLogic.textColor
property variant backendValue;
implicitWidth: 74
ExtendedFunctionButton {
x: 2
x: 4
anchors.verticalCenter: parent.verticalCenter
backendValue: spinBox.backendValue
visible: spinBox.enabled
@@ -59,4 +61,5 @@ Controls.SpinBox {
style: CustomSpinBoxStyle {
}
}

View File

@@ -191,8 +191,8 @@ TextEditor_CurrentLine_ScrollBarColor=ffffffff
ProjectExplorer_TaskError_TextMarkColor=error
ProjectExplorer_TaskWarn_TextMarkColor=warning
ClangCodeModel_Error_TextMarkColor=error
ClangCodeModel_Warning_TextMarkColor=warning
CodeModel_Error_TextMarkColor=error
CodeModel_Warning_TextMarkColor=warning
PaletteWindow=normalBackground
PaletteWindowText=text

View File

@@ -184,8 +184,8 @@ TextEditor_CurrentLine_ScrollBarColor=ff404040
ProjectExplorer_TaskError_TextMarkColor=error
ProjectExplorer_TaskWarn_TextMarkColor=warning
ClangCodeModel_Error_TextMarkColor=error
ClangCodeModel_Warning_TextMarkColor=warning
CodeModel_Error_TextMarkColor=error
CodeModel_Warning_TextMarkColor=warning
QmlDesigner_BackgroundColor=qmlDesignerButtonColor
QmlDesigner_HighlightColor=ff46a2da

View File

@@ -195,8 +195,8 @@ TextEditor_CurrentLine_ScrollBarColor=ffffffff
ProjectExplorer_TaskError_TextMarkColor=error
ProjectExplorer_TaskWarn_TextMarkColor=warning
ClangCodeModel_Error_TextMarkColor=error
ClangCodeModel_Warning_TextMarkColor=warning
CodeModel_Error_TextMarkColor=error
CodeModel_Warning_TextMarkColor=warning
QmlDesigner_BackgroundColor=qmlDesignerButtonColor
QmlDesigner_HighlightColor=ff3f91c4

View File

@@ -193,8 +193,8 @@ TextEditor_CurrentLine_ScrollBarColor=ff404040
ProjectExplorer_TaskError_TextMarkColor=error
ProjectExplorer_TaskWarn_TextMarkColor=warning
ClangCodeModel_Error_TextMarkColor=error
ClangCodeModel_Warning_TextMarkColor=warning
CodeModel_Error_TextMarkColor=error
CodeModel_Warning_TextMarkColor=warning
QmlDesigner_BackgroundColor=qmlDesignerButtonColor
QmlDesigner_HighlightColor=ff46a2da

View File

@@ -191,8 +191,8 @@ TextEditor_CurrentLine_ScrollBarColor=ff404040
ProjectExplorer_TaskError_TextMarkColor=error
ProjectExplorer_TaskWarn_TextMarkColor=warning
ClangCodeModel_Error_TextMarkColor=error
ClangCodeModel_Warning_TextMarkColor=warning
CodeModel_Error_TextMarkColor=error
CodeModel_Warning_TextMarkColor=warning
QmlDesigner_BackgroundColor=qmlDesignerButtonColor
QmlDesigner_HighlightColor=ff46a2da

View File

@@ -54,11 +54,18 @@ Item {
}
function prettyPrintScale(amount) {
var sign;
if (amount < 0) {
sign = "-";
amount = -amount;
} else {
sign = "";
}
var unitOffset = 0;
var unitAmount = 1;
for (unitOffset = 0; amount > unitAmount * 1024; ++unitOffset, unitAmount *= 1024) {}
var result = amount / unitAmount;
return roundTo3Digits(result) + units[unitOffset];
return sign + roundTo3Digits(result) + units[unitOffset];
}
Connections {
@@ -134,7 +141,7 @@ Item {
anchors.bottomMargin: 2
anchors.leftMargin: 2
anchors.left: parent.left
text: prettyPrintScale(index * row.stepVal)
text: prettyPrintScale(row.minVal + index * row.stepVal)
}
Rectangle {

View File

@@ -212,6 +212,11 @@ public:
IconsCodeModelOverlayBackgroundColor,
IconsCodeModelOverlayForegroundColor,
/* Code model text marks */
CodeModel_Error_TextMarkColor,
CodeModel_Warning_TextMarkColor,
/* Output panes */
OutputPanes_DebugTextColor,
@@ -287,10 +292,6 @@ public:
ProjectExplorer_TaskError_TextMarkColor,
ProjectExplorer_TaskWarn_TextMarkColor,
/* ClangCodeModel Plugin */
ClangCodeModel_Error_TextMarkColor,
ClangCodeModel_Warning_TextMarkColor,
/* QmlDesigner Plugin */
QmlDesigner_BackgroundColor,
QmlDesigner_HighlightColor,

View File

@@ -46,7 +46,6 @@ HEADERS += \
android_global.h \
androidbuildapkstep.h \
androidbuildapkwidget.h \
androidrunnable.h \
androidtoolmanager.h \
androidsdkmanager.h \
androidavdmanager.h \
@@ -94,7 +93,6 @@ SOURCES += \
androidbuildapkstep.cpp \
androidbuildapkwidget.cpp \
androidqtsupport.cpp \
androidrunnable.cpp \
androidtoolmanager.cpp \
androidsdkmanager.cpp \
androidavdmanager.cpp \

View File

@@ -86,8 +86,6 @@ Project {
"androidrunconfiguration.h",
"androidruncontrol.cpp",
"androidruncontrol.h",
"androidrunnable.cpp",
"androidrunnable.h",
"androidrunner.cpp",
"androidrunner.h",
"androidrunnerworker.cpp",

View File

@@ -297,6 +297,7 @@ bool AndroidAvdManager::startAvdAsync(const QString &avdName) const
return false;
}
QProcess *avdProcess = new QProcess();
avdProcess->setReadChannelMode(QProcess::MergedChannels);
QObject::connect(avdProcess,
static_cast<void (QProcess::*)(int)>(&QProcess::finished),
avdProcess,

View File

@@ -232,3 +232,4 @@ private:
} // namespace Android
Q_DECLARE_METATYPE(Android::AndroidDeviceInfo)

View File

@@ -51,9 +51,11 @@ const char ANDROID_SETTINGS_ID[] = "BB.Android Configurations";
const char ANDROID_TOOLCHAIN_ID[] = "Qt4ProjectManager.ToolChain.Android";
const char ANDROIDQT[] = "Qt4ProjectManager.QtVersion.Android";
const char ANDROID_AMSTARTARGS_ASPECT[] = "Android.AmStartArgs";
const char ANDROID_PRESTARTSHELLCMDLIST_ASPECT[] = "Android.PreStartShellCmdList";
const char ANDROID_POSTSTARTSHELLCMDLIST_ASPECT[] = "Android.PostStartShellCmdList";
const char ANDROID_AMSTARTARGS[] = "Android.AmStartArgs";
// Note: Can be set on RunConfiguration using an aspect and/or
// 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_ID[] = "Android Device";
@@ -69,6 +71,7 @@ const char ANDROID_DEPLOY_SETTINGS_FILE[] = "AndroidDeploySettingsFile";
const char ANDROID_PACKAGE_SOURCE_DIR[] = "AndroidPackageSourceDir";
const char ANDROID_EXTRA_LIBS[] = "AndroidExtraLibs";
const char ANDROID_PACKAGENAME[] = "Android.PackageName";
const char ANDROID_PACKAGE_INSTALLATION_STEP_ID[] = "Qt4ProjectManager.AndroidPackageInstallationStep";
} // namespace Constants;

View File

@@ -111,20 +111,20 @@ AndroidRunConfiguration::AndroidRunConfiguration(Target *target, Core::Id id)
: RunConfiguration(target, id)
{
auto amStartArgsAspect = new BaseStringAspect(this);
amStartArgsAspect->setId(Constants::ANDROID_AMSTARTARGS_ASPECT);
amStartArgsAspect->setId(Constants::ANDROID_AMSTARTARGS);
amStartArgsAspect->setSettingsKey("Android.AmStartArgsKey");
amStartArgsAspect->setLabelText(tr("Activity manager start options:"));
amStartArgsAspect->setDisplayStyle(BaseStringAspect::LineEditDisplay);
addExtraAspect(amStartArgsAspect);
auto preStartShellCmdAspect = new BaseStringListAspect(this);
preStartShellCmdAspect->setId(Constants::ANDROID_PRESTARTSHELLCMDLIST_ASPECT);
preStartShellCmdAspect->setId(Constants::ANDROID_PRESTARTSHELLCMDLIST);
preStartShellCmdAspect->setSettingsKey("Android.PreStartShellCmdListKey");
preStartShellCmdAspect->setLabel(tr("Shell commands to run on Android device before application launch."));
addExtraAspect(preStartShellCmdAspect);
auto postStartShellCmdAspect = new BaseStringListAspect(this);
postStartShellCmdAspect->setId(Constants::ANDROID_POSTSTARTSHELLCMDLIST_ASPECT);
postStartShellCmdAspect->setId(Constants::ANDROID_POSTFINISHSHELLCMDLIST);
postStartShellCmdAspect->setSettingsKey("Android.PostStartShellCmdListKey");
postStartShellCmdAspect->setLabel(tr("Shell commands to run on Android device after application quits."));
addExtraAspect(postStartShellCmdAspect);
@@ -140,7 +140,7 @@ QWidget *AndroidRunConfiguration::createConfigurationWidget()
auto widget = new QWidget;
auto layout = new QFormLayout(widget);
extraAspect(Constants::ANDROID_AMSTARTARGS_ASPECT)->addToConfigurationLayout(layout);
extraAspect(Constants::ANDROID_AMSTARTARGS)->addToConfigurationLayout(layout);
auto warningIconLabel = new QLabel;
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."));
layout->addRow(warningIconLabel, warningLabel);
extraAspect(Constants::ANDROID_PRESTARTSHELLCMDLIST_ASPECT)->addToConfigurationLayout(layout);
extraAspect(Constants::ANDROID_POSTSTARTSHELLCMDLIST_ASPECT)->addToConfigurationLayout(layout);
extraAspect(Constants::ANDROID_PRESTARTSHELLCMDLIST)->addToConfigurationLayout(layout);
extraAspect(Constants::ANDROID_POSTFINISHSHELLCMDLIST)->addToConfigurationLayout(layout);
auto wrapped = wrapWidget(widget);
auto detailsWidget = qobject_cast<DetailsWidget *>(wrapped);

View File

@@ -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

View File

@@ -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)

View File

@@ -120,7 +120,8 @@ AndroidRunner::AndroidRunner(RunControl *runControl,
setDisplayName("AndroidRunner");
static const int metaTypes[] = {
qRegisterMetaType<QVector<QStringList> >("QVector<QStringList>"),
qRegisterMetaType<Utils::Port>("Utils::Port")
qRegisterMetaType<Utils::Port>("Utils::Port"),
qRegisterMetaType<AndroidDeviceInfo>("Android::AndroidDeviceInfo")
};
Q_UNUSED(metaTypes);
@@ -128,21 +129,10 @@ AndroidRunner::AndroidRunner(RunControl *runControl,
connect(&m_checkAVDTimer, &QTimer::timeout, this, &AndroidRunner::checkAVD);
QString intent = intentName.isEmpty() ? AndroidManager::intentName(m_target) : intentName;
m_androidRunnable.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));
}
m_packageName = intent.left(intent.indexOf('/'));
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->setIsPreNougat(apiLevel <= 23);
m_worker->setExtraAppParams(extraAppParams);
@@ -193,7 +183,7 @@ void AndroidRunner::stop()
{
if (m_checkAVDTimer.isActive()) {
m_checkAVDTimer.stop();
appendMessage("\n\n" + tr("\"%1\" terminated.").arg(m_androidRunnable.packageName),
appendMessage("\n\n" + tr("\"%1\" terminated.").arg(m_packageName),
Utils::DebugFormat);
return;
}
@@ -258,7 +248,7 @@ void AndroidRunner::launchAVD()
emit androidDeviceInfoChanged(info);
if (info.isValid()) {
AndroidAvdManager avdManager;
if (avdManager.findAvd(info.avdname).isEmpty()) {
if (!info.avdname.isEmpty() && avdManager.findAvd(info.avdname).isEmpty()) {
bool launched = avdManager.startAvdAsync(info.avdname);
m_launchedAVDName = launched ? info.avdname:"";
} else {

View File

@@ -26,7 +26,6 @@
#pragma once
#include "androidconfigurations.h"
#include "androidrunnable.h"
#include <projectexplorer/runconfiguration.h>
#include <qmldebug/qmldebugcommandlinearguments.h>
@@ -67,7 +66,7 @@ signals:
void asyncStart();
void asyncStop();
void qmlServerReady(const QUrl &serverUrl);
void androidDeviceInfoChanged(const AndroidDeviceInfo &deviceInfo);
void androidDeviceInfoChanged(const Android::AndroidDeviceInfo &deviceInfo);
void avdDetected();
private:
@@ -80,7 +79,7 @@ private:
void checkAVD();
void launchAVD();
AndroidRunnable m_androidRunnable;
QString m_packageName;
QString m_launchedAVDName;
QThread m_thread;
QTimer m_checkAVDTimer;

View File

@@ -140,8 +140,8 @@ static void deleter(QProcess *p)
p->deleteLater();
}
AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const AndroidRunnable &runnable)
: m_androidRunnable(runnable)
AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const QString &packageName)
: m_packageName(packageName)
, m_adbLogcatProcess(nullptr, deleter)
, m_psIsAlive(nullptr, deleter)
, m_logCatRegExp(regExpLogcat)
@@ -181,8 +181,22 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const AndroidRunnabl
m_deviceSerialNumber = AndroidManager::deviceSerialNumber(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(' ');
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()
@@ -229,7 +243,7 @@ bool AndroidRunnerWorker::runAdb(const QStringList &args, int timeoutS)
void AndroidRunnerWorker::adbKill(qint64 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
@@ -239,14 +253,14 @@ QStringList AndroidRunnerWorker::selector() const
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
const QByteArray out = Utils::SynchronousProcess()
.runBlocking(m_adb, selector() << QStringLiteral("shell") << pidScriptPreNougat)
.allRawOutput();
qint64 pid = extractPID(out.simplified(), m_androidRunnable.packageName);
qint64 pid = extractPID(out.simplified(), m_packageName);
if (pid != -1) {
adbKill(pid);
}
@@ -346,7 +360,7 @@ void AndroidRunnerWorker::asyncStartHelper()
QTC_ASSERT(!m_adbLogcatProcess, /**/);
m_adbLogcatProcess = std::move(logcatProcess);
for (const QString &entry: m_androidRunnable.beforeStartAdbCommands)
for (const QString &entry : m_beforeStartAdbCommands)
runAdb(entry.split(' ', QString::SkipEmptyParts));
QStringList args({"shell", "am", "start"});
@@ -356,14 +370,14 @@ void AndroidRunnerWorker::asyncStartHelper()
args << "-D";
QString gdbServerSocket;
// 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));
return;
}
gdbServerSocket = QString::fromUtf8(m_lastRunAdbRawOutput.trimmed()) + "/debug-socket";
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));
return;
}
@@ -380,11 +394,11 @@ void AndroidRunnerWorker::asyncStartHelper()
return;
}
runAdb({"shell", "run-as", m_androidRunnable.packageName, "killall", gdbServerExecutable});
runAdb({"shell", "run-as", m_androidRunnable.packageName, "rm", gdbServerSocket});
runAdb({"shell", "run-as", m_packageName, "killall", gdbServerExecutable});
runAdb({"shell", "run-as", m_packageName, "rm", gdbServerSocket});
std::unique_ptr<QProcess, Deleter> gdbServerProcess(new QProcess, deleter);
gdbServerProcess->start(m_adb, selector() << "shell" << "run-as"
<< m_androidRunnable.packageName << "lib/" + gdbServerExecutable
<< m_packageName << "lib/" + gdbServerExecutable
<< "--multi" << "+" + gdbServerSocket);
if (!gdbServerProcess->waitForStarted()) {
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));
return;
}
m_androidRunnable.afterFinishAdbCommands.push_back(removeForward.join(' '));
m_afterFinishAdbCommands.push_back(removeForward.join(' '));
}
if (m_qmlDebugServices != QmlDebug::NoQmlDebugServices) {
@@ -411,7 +425,7 @@ void AndroidRunnerWorker::asyncStartHelper()
.arg(m_lastRunAdbError));
return;
}
m_androidRunnable.afterFinishAdbCommands.push_back(removeForward.join(' '));
m_afterFinishAdbCommands.push_back(removeForward.join(' '));
args << "-e" << "qml_debug" << "true"
<< "-e" << "qmljsdebugger"
@@ -442,7 +456,7 @@ void AndroidRunnerWorker::asyncStart()
asyncStartHelper();
m_pidFinder = Utils::onResultReady(Utils::runAsync(findProcessPID, m_adb, selector(),
m_androidRunnable.packageName, m_isPreNougat),
m_packageName, m_isPreNougat),
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));
return;
}
m_androidRunnable.afterFinishAdbCommands.push_back(removeForward.join(' '));
m_afterFinishAdbCommands.push_back(removeForward.join(' '));
auto jdbPath = AndroidConfigurations::currentConfig().openJDKLocation().appendPath("bin");
if (Utils::HostOsInfo::isWindowsHost())
@@ -527,7 +541,7 @@ void AndroidRunnerWorker::onProcessIdChanged(qint64 pid)
m_processPID = pid;
if (pid == -1) {
emit remoteProcessFinished(QLatin1String("\n\n") + tr("\"%1\" died.")
.arg(m_androidRunnable.packageName));
.arg(m_packageName));
// App died/killed. Reset log, monitor, jdb & gdb processes.
m_adbLogcatProcess.reset();
m_psIsAlive.reset();
@@ -535,7 +549,7 @@ void AndroidRunnerWorker::onProcessIdChanged(qint64 pid)
m_gdbServerProcess.reset();
// Run adb commands after application quit.
for (const QString &entry: m_androidRunnable.afterFinishAdbCommands)
for (const QString &entry: m_afterFinishAdbCommands)
runAdb(entry.split(' ', QString::SkipEmptyParts));
} else {
// In debugging cases this will be funneled to the engine to actually start

View File

@@ -26,12 +26,12 @@
#pragma once
#include <projectexplorer/runconfiguration.h>
#include <qmldebug/qmldebugcommandlinearguments.h>
#include <QFuture>
#include "androidrunnable.h"
namespace Android {
class AndroidDeviceInfo;
@@ -44,7 +44,7 @@ class AndroidRunnerWorker : public QObject
{
Q_OBJECT
public:
AndroidRunnerWorker(ProjectExplorer::RunWorker *runner, const AndroidRunnable &runnable);
AndroidRunnerWorker(ProjectExplorer::RunWorker *runner, const QString &packageName);
~AndroidRunnerWorker() override;
bool adbShellAmNeedsQuotes();
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
bool m_isPreNougat = false;
AndroidRunnable m_androidRunnable;
QString m_packageName;
QString m_intentName;
QStringList m_beforeStartAdbCommands;
QStringList m_afterFinishAdbCommands;
QString m_adb;
QStringList m_amStartExtraArgs;
qint64 m_processPID = -1;

View File

@@ -48,7 +48,6 @@
#include <utils/hostosinfo.h>
#include <utils/outputformat.h>
#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
#include <QComboBox>
#include <QDialogButtonBox>
@@ -56,8 +55,9 @@
#include <QFuture>
#include <QFutureInterface>
#include <QLabel>
#include <QProcess>
#include <QPushButton>
#include <QTime>
#include <QTimer>
#include <debugger/debuggerkitinformation.h>
#include <debugger/debuggerruncontrol.h>
@@ -88,9 +88,9 @@ TestRunner::TestRunner(QObject *parent) :
&m_futureWatcher, &QFutureWatcher<TestResultPtr>::cancel);
connect(&m_futureWatcher, &QFutureWatcher<TestResultPtr>::canceled,
this, [this]() {
cancelCurrent(UserCanceled);
emit testResultReady(TestResultPtr(new FaultyTestResult(
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)
{
QTC_ASSERT(!m_executingTests, return);
qDeleteAll(m_selectedTests);
m_selectedTests.clear();
m_selectedTests = selected;
m_selectedTests.append(selected);
}
void TestRunner::runTest(TestRunMode mode, const TestTreeItem *item)
{
QTC_ASSERT(!m_executingTests, return);
TestConfiguration *configuration = item->asConfiguration(mode);
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" };
if (Utils::HostOsInfo::isLinuxHost())
important.append("LD_LIBRARY_PATH");
else if (Utils::HostOsInfo::isMacHost())
important.append({ "DYLD_LIBRARY_PATH", "DYLD_FRAMEWORK_PATH" });
const QProcessEnvironment &environment = proc.processEnvironment();
const QProcessEnvironment &environment = proc->processEnvironment();
for (const QString &var : important)
information.append('\n' + var + ": " + environment.value(var));
return information;
@@ -142,133 +145,131 @@ static QString rcInfo(const TestConfiguration * const config)
static QString constructOmittedDetailsString(const QStringList &omitted)
{
QString details = TestRunner::tr("Omitted the following arguments specified on the run "
"configuration page for \"%1\":");
for (const QString &arg : omitted)
details += "\n" + arg;
return details;
return TestRunner::tr("Omitted the following arguments specified on the run "
"configuration page for \"%1\":") + '\n' + omitted.join('\n');
}
static void performTestRun(QFutureInterface<TestResultPtr> &futureInterface,
const QList<TestConfiguration *> selectedTests,
const TestSettings &settings)
void TestRunner::scheduleNext()
{
const int timeout = settings.timeout;
const bool omitRunConfigWarnings = settings.omitRunConfigWarn;
QEventLoop eventLoop;
int testCaseCount = 0;
for (TestConfiguration *config : selectedTests) {
config->completeTestInformation(TestRunMode::Run);
if (config->project()) {
testCaseCount += config->testCaseCount();
if (!omitRunConfigWarnings && config->isGuessed()) {
QString message = TestRunner::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());
futureInterface.reportResult(
TestResultPtr(new FaultyTestResult(Result::MessageWarn, message)));
}
} else {
futureInterface.reportResult(TestResultPtr(new FaultyTestResult(Result::MessageWarn,
TestRunner::tr("Project is null for \"%1\". Removing from test run.\n"
"Check the test environment.").arg(config->displayName()))));
}
}
QTC_ASSERT(!m_selectedTests.isEmpty(), onFinished(); return);
QTC_ASSERT(!m_currentConfig && !m_currentProcess, resetInternalPointers());
QTC_ASSERT(m_fakeFutureInterface, onFinished(); return);
QProcess testProcess;
testProcess.setReadChannel(QProcess::StandardOutput);
m_currentConfig = m_selectedTests.dequeue();
futureInterface.setProgressRange(0, testCaseCount);
futureInterface.setProgressValue(0);
for (const TestConfiguration *testConfiguration : selectedTests) {
QString commandFilePath = testConfiguration->executableFilePath();
QString commandFilePath = m_currentConfig->executableFilePath();
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();
emit testResultReady(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
tr("Executable path is empty. (%1)").arg(m_currentConfig->displayName()))));
delete m_currentConfig;
m_currentConfig = nullptr;
if (m_selectedTests.isEmpty())
onFinished();
else
onProcessFinished();
return;
}
eventLoop.processEvents();
if (!m_currentConfig->project())
onProcessFinished();
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()))));
}
} else {
futureInterface.reportResult(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
TestRunner::tr("Failed to start test for project \"%1\".")
.arg(testConfiguration->displayName()) + processInformation(testProcess)
+ rcInfo(testConfiguration))));
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))));
}
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();
void TestRunner::cancelCurrent(TestRunner::CancelReason reason)
{
if (reason == UserCanceled) {
if (!m_fakeFutureInterface->isCanceled()) // depends on using the button / progress bar
m_fakeFutureInterface->reportCanceled();
}
futureInterface.reportResult(TestResultPtr(
new FaultyTestResult(Result::MessageFatal, TestRunner::tr(
"Test case canceled due to timeout.\nMaybe raise the timeout?"))));
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?"))));
}
}
futureInterface.setProgressValue(testCaseCount);
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))));
}
}
resetInternalPointers();
if (!m_selectedTests.isEmpty() && !m_fakeFutureInterface->isCanceled()) {
scheduleNext();
} else {
m_fakeFutureInterface->reportFinished();
onFinished();
}
}
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)
{
QTC_ASSERT(!m_executingTests, return);
m_runMode = mode;
ProjectExplorer::Internal::ProjectExplorerSettings projectExplorerSettings =
ProjectExplorer::ProjectExplorerPlugin::projectExplorerSettings();
@@ -358,6 +359,32 @@ static ProjectExplorer::RunConfiguration *getRunConfiguration(const QString &dia
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()
{
QList<TestConfiguration *> toBeRemoved;
@@ -381,10 +408,17 @@ void TestRunner::runTests()
return;
}
QFuture<TestResultPtr> future = Utils::runAsync(&performTestRun, m_selectedTests,
*AutotestPlugin::settings());
int testCaseCount = precheckTestConfigurations();
// 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);
Core::ProgressManager::addTask(future, tr("Running Tests"), Autotest::Constants::TASK_INDEX);
scheduleNext();
}
static void processOutput(TestOutputReader *outputreader, const QString &msg,
@@ -552,6 +586,11 @@ void TestRunner::buildFinished(bool success)
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;
emit testRunFinished();
}

View File

@@ -31,12 +31,13 @@
#include <QDialog>
#include <QFutureWatcher>
#include <QObject>
#include <QProcess>
#include <QQueue>
QT_BEGIN_NAMESPACE
class QComboBox;
class QDialogButtonBox;
class QLabel;
class QProcess;
QT_END_NAMESPACE
namespace ProjectExplorer {
@@ -51,6 +52,8 @@ class TestRunner : public QObject
Q_OBJECT
public:
enum CancelReason { UserCanceled, Timeout };
static TestRunner* instance();
~TestRunner();
@@ -71,14 +74,24 @@ private:
void buildFinished(bool success);
void onFinished();
int precheckTestConfigurations();
void scheduleNext();
void cancelCurrent(CancelReason reason);
void onProcessFinished();
void resetInternalPointers();
void runTests();
void debugTests();
void runOrDebugTests();
explicit TestRunner(QObject *parent = 0);
QFutureWatcher<TestResultPtr> m_futureWatcher;
QList<TestConfiguration *> m_selectedTests;
bool m_executingTests;
QFutureInterface<TestResultPtr> *m_fakeFutureInterface = nullptr;
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;
// temporarily used if building before running is necessary

View File

@@ -83,8 +83,8 @@ ClangTextMark::ClangTextMark(const FileName &fileName,
updateIcon();
if (fullVisualization) {
setLineAnnotation(Utils::diagnosticCategoryPrefixRemoved(diagnostic.text.toString()));
setColor(warning ? ::Utils::Theme::ClangCodeModel_Warning_TextMarkColor
: ::Utils::Theme::ClangCodeModel_Error_TextMarkColor);
setColor(warning ? ::Utils::Theme::CodeModel_Warning_TextMarkColor
: ::Utils::Theme::CodeModel_Error_TextMarkColor);
}
}

View File

@@ -161,6 +161,10 @@ ClangTidyClazyTool::ClangTidyClazyTool()
// Apply fixits button
m_applyFixitsButton = new QToolButton;
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]() {
QVector<Diagnostic> diagnosticsWithFixits;

View File

@@ -6,6 +6,7 @@ QtcPlugin {
Depends { name: "Debugger" }
Depends { name: "Core" }
Depends { name: "TextEditor" }
Depends { name: "CppTools" }
Depends { name: "ExtensionSystem" }
Depends { name: "ProjectExplorer" }

View File

@@ -34,7 +34,6 @@
#include <utils/qtcassert.h>
#include <utils/utilsicons.h>
#include <QCoreApplication>
#include <QFileInfo>
#include <cmath>
@@ -61,8 +60,13 @@ ClangToolsDiagnosticModel::ClangToolsDiagnosticModel(QObject *parent)
void ClangToolsDiagnosticModel::addDiagnostics(const QList<Diagnostic> &diagnostics)
{
foreach (const Diagnostic &d, diagnostics)
rootItem()->appendChild(new DiagnosticItem(d));
const auto onFixItChanged = [this](bool checked){
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
@@ -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.
if (diag.explainingSteps.count() == 1) {
@@ -214,21 +220,15 @@ DiagnosticItem::DiagnosticItem(const Diagnostic &diag) : m_diagnostic(diag)
Qt::ItemFlags DiagnosticItem::flags(int column) const
{
if (column == DiagnosticView::FixItColumn && m_diagnostic.hasFixits)
return TreeItem::flags(column) | Qt::ItemIsUserCheckable;
return TreeItem::flags(column);
const Qt::ItemFlags itemFlags = TreeItem::flags(column);
if (column == DiagnosticView::FixItColumn) {
if (m_diagnostic.hasFixits)
return itemFlags | Qt::ItemIsUserCheckable;
else
return itemFlags & ~Qt::ItemIsEnabled;
}
static QVariant locationData(int role, const Debugger::DiagnosticLocation &location)
{
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)
@@ -247,7 +247,7 @@ static QVariant iconData(const QString &type)
QVariant DiagnosticItem::data(int column, int role) const
{
if (column == Debugger::DetailedErrorView::LocationColumn)
return locationData(role, m_diagnostic.location);
return Debugger::DetailedErrorView::locationData(role, m_diagnostic.location);
if (column == DiagnosticView::FixItColumn) {
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) {
m_applyFixits = data.value<Qt::CheckState>() == Qt::Checked ? true : false;
update();
if (m_onCheckedFixit)
m_onCheckedFixit(m_applyFixits);
return true;
}
@@ -290,7 +292,7 @@ ExplainingStepItem::ExplainingStepItem(const ExplainingStep &step) : m_step(step
QVariant ExplainingStepItem::data(int column, int role) const
{
if (column == Debugger::DetailedErrorView::LocationColumn)
return locationData(role, m_step.location);
return Debugger::DetailedErrorView::locationData(role, m_step.location);
if (column == DiagnosticView::FixItColumn)
return QVariant();

View File

@@ -35,6 +35,8 @@
#include <QPointer>
#include <QSortFilterProxyModel>
#include <functional>
namespace ProjectExplorer { class Project; }
namespace ClangTools {
@@ -43,7 +45,8 @@ namespace Internal {
class DiagnosticItem : public Utils::TreeItem
{
public:
DiagnosticItem(const Diagnostic &diag);
using OnCheckedFixit = std::function<void(bool)>;
DiagnosticItem(const Diagnostic &diag, const OnCheckedFixit &onCheckedFixit);
Diagnostic diagnostic() const { return m_diagnostic; }
bool applyFixits() const { return m_applyFixits; }
@@ -56,6 +59,7 @@ private:
private:
const Diagnostic m_diagnostic;
bool m_applyFixits = false;
OnCheckedFixit m_onCheckedFixit;
};
class ClangToolsDiagnosticModel : public Utils::TreeModel<>
@@ -71,6 +75,12 @@ public:
enum ItemRole {
DiagnosticRole = Debugger::DetailedErrorView::FullTextRole + 1
};
signals:
void fixItsToApplyCountChanged(int count);
private:
int m_fixItsToApplyCount = 0;
};
class DiagnosticFilterModel : public QSortFilterProxyModel

View File

@@ -196,6 +196,12 @@ void BuildDirManager::setParametersAndRequestParse(const BuildDirParameters &par
int newReaderReparseOptions,
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);
if (m_reader)

View File

@@ -279,8 +279,7 @@ static std::vector<std::unique_ptr<FileNode>> &&
removeKnownNodes(const QSet<Utils::FileName> &knownFiles,
std::vector<std::unique_ptr<FileNode>> &&files)
{
std::remove_if(std::begin(files), std::end(files),
[&knownFiles](const std::unique_ptr<FileNode> &n) {
Utils::erase(files, [&knownFiles](const std::unique_ptr<FileNode> &n) {
return knownFiles.contains(n->filePath());
});
return std::move(files);

View File

@@ -19,6 +19,108 @@
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string notr="true">&amp;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">&amp;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 &amp;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">&amp;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">&amp;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&amp;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">
<attribute name="title">
<string notr="true">&amp;Snapshots and Documents</string>
@@ -182,108 +284,6 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string notr="true">&amp;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">&amp;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 &amp;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">&amp;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">&amp;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&amp;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">
<attribute name="title">
<string notr="true">&amp;Working Copy</string>

View File

@@ -41,91 +41,14 @@
#include <QHeaderView>
#include <QMenu>
#include <QPainter>
#include <QSharedPointer>
#include <QTextDocument>
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) :
QTreeView(parent),
m_copyAction(new QAction(this))
{
header()->setSectionResizeMode(QHeaderView::ResizeToContents);
setItemDelegateForColumn(LocationColumn, new Internal::DetailedErrorDelegate(this));
m_copyAction->setText(tr("Copy"));
m_copyAction->setIcon(Utils::Icons::COPY.icon());
@@ -187,6 +110,31 @@ void DetailedErrorView::goBack()
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
{
return model() ? model()->rowCount() : 0;
@@ -218,5 +166,3 @@ void DetailedErrorView::setCurrentRow(int row)
}
} // namespace Debugger
#include "detailederrorview.moc"

View File

@@ -32,6 +32,8 @@
namespace Debugger {
class DiagnosticLocation;
class DEBUGGER_EXPORT DetailedErrorView : public QTreeView
{
Q_OBJECT
@@ -53,6 +55,8 @@ public:
LocationColumn,
};
static QVariant locationData(int role, const DiagnosticLocation &location);
private:
void contextMenuEvent(QContextMenuEvent *e) override;
void currentChanged(const QModelIndex &current, const QModelIndex &previous) override;

View File

@@ -179,6 +179,7 @@ SideDiffEditorWidget::SideDiffEditorWidget(QWidget *parent)
connect(documentLayout, &TextDocumentLayout::foldChanged,
this, &SideDiffEditorWidget::foldChanged);
setCodeFoldingSupported(true);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
}
void SideDiffEditorWidget::saveState()
@@ -714,6 +715,13 @@ SideBySideDiffEditorWidget::SideBySideDiffEditorWidget(QWidget *parent)
connect(m_rightEditor, &SideDiffEditorWidget::foldChanged,
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->addWidget(m_leftEditor);
@@ -1133,6 +1141,18 @@ void SideBySideDiffEditorWidget::rightCursorPositionChanged()
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)
{
if (m_controller.m_ignoreCurrentIndexChange)

View File

@@ -95,6 +95,7 @@ private:
void rightHSliderChanged();
void leftCursorPositionChanged();
void rightCursorPositionChanged();
void syncHorizontalScrollBarPolicy();
void handlePositionChange(SideDiffEditorWidget *source, SideDiffEditorWidget *dest);
void syncCursor(SideDiffEditorWidget *source, SideDiffEditorWidget *dest);

View File

@@ -337,22 +337,4 @@ BuildStep *BuildStepFactory::restore(BuildStepList *parent, const QVariantMap &m
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

View File

@@ -132,7 +132,6 @@ public:
Core::Id stepId() const;
BuildStep *create(BuildStepList *parent, Core::Id id);
BuildStep *restore(BuildStepList *parent, const QVariantMap &map);
BuildStep *clone(BuildStepList *parent, BuildStep *product);
virtual bool canHandle(BuildStepList *bsl) const;

View File

@@ -701,6 +701,11 @@ void Project::createTargetFromMap(const QVariantMap &map, int index)
Target *t = restoreTarget(targetMap);
if (!t)
return;
if (t->runConfigurations().isEmpty() && t->buildConfigurations().isEmpty()) {
delete t;
return;
}
addTarget(t);
}

View File

@@ -33,6 +33,7 @@
#include <coreplugin/messagebox.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <QQmlContext>
@@ -135,15 +136,13 @@ QStringList PropertyEditorContextObject::autoComplete(const QString &text, int p
void PropertyEditorContextObject::toogleExportAlias()
{
if (!m_model || !m_model->rewriterView())
return;
QTC_ASSERT(m_model && m_model->rewriterView(), return);
/* Ideally we should not missuse the rewriterView
* If we add more code here we have to forward the property editor view */
RewriterView *rewriterView = m_model->rewriterView();
if (rewriterView->selectedModelNodes().isEmpty())
return;
QTC_ASSERT(!rewriterView->selectedModelNodes().isEmpty(), return);
const ModelNode selectedNode = rewriterView->selectedModelNodes().constFirst();
@@ -174,15 +173,13 @@ void PropertyEditorContextObject::toogleExportAlias()
void PropertyEditorContextObject::changeTypeName(const QString &typeName)
{
if (!m_model || !m_model->rewriterView())
return;
QTC_ASSERT(m_model && m_model->rewriterView(), return);
/* Ideally we should not missuse the rewriterView
* If we add more code here we have to forward the property editor view */
RewriterView *rewriterView = m_model->rewriterView();
if (rewriterView->selectedModelNodes().isEmpty())
return;
QTC_ASSERT(!rewriterView->selectedModelNodes().isEmpty(), return);
ModelNode selectedNode = rewriterView->selectedModelNodes().constFirst();
@@ -210,15 +207,13 @@ void PropertyEditorContextObject::changeTypeName(const QString &typeName)
void PropertyEditorContextObject::insertKeyframe(const QString &propertyName)
{
if (!m_model || !m_model->rewriterView())
return;
QTC_ASSERT(m_model && m_model->rewriterView(), return);
/* Ideally we should not missuse the rewriterView
* If we add more code here we have to forward the property editor view */
RewriterView *rewriterView = m_model->rewriterView();
if (rewriterView->selectedModelNodes().isEmpty())
return;
QTC_ASSERT(!rewriterView->selectedModelNodes().isEmpty(), return);
ModelNode selectedNode = rewriterView->selectedModelNodes().constFirst();

View File

@@ -271,6 +271,8 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q
if (qmlObjectNode.isValid()) {
m_contextObject->setModel(propertyEditor->model());
qCInfo(propertyEditorBenchmark) << Q_FUNC_INFO;
QTime time;

View File

@@ -90,8 +90,8 @@ void QmlJSTextMark::init(bool warning, const QString message)
{
setIcon(warning ? Utils::Icons::CODEMODEL_WARNING.icon()
: Utils::Icons::CODEMODEL_ERROR.icon());
setColor(warning ? Utils::Theme::ClangCodeModel_Warning_TextMarkColor
: Utils::Theme::ClangCodeModel_Error_TextMarkColor);
setColor(warning ? Utils::Theme::CodeModel_Warning_TextMarkColor
: Utils::Theme::CodeModel_Error_TextMarkColor);
setDefaultToolTip(warning ? QApplication::translate("QmlJS Code Model Marks", "Code Model Warning")
: QApplication::translate("QmlJS Code Model Marks", "Code Model Error"));
setToolTip(message);

View File

@@ -5363,7 +5363,6 @@ void TextEditorWidgetPrivate::updateCurrentLineInScrollbar()
{
if (m_highlightCurrentLine && m_highlightScrollBarController) {
m_highlightScrollBarController->removeHighlights(Constants::SCROLL_BAR_CURRENT_LINE);
if (m_highlightScrollBarController->scrollBar()->maximum() > 0) {
const QTextCursor &tc = q->textCursor();
if (QTextLayout *layout = tc.block().layout()) {
const int pos = q->textCursor().block().firstLineNumber() +
@@ -5374,7 +5373,6 @@ void TextEditorWidgetPrivate::updateCurrentLineInScrollbar()
}
}
}
}
void TextEditorWidgetPrivate::slotUpdateBlockNotify(const QTextBlock &block)
{

View File

@@ -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) {
case Debugger::DetailedErrorView::LocationRole:
return QVariant::fromValue(Debugger::DiagnosticLocation(frame.filePath(), frame.line(), 0));
case Qt::ToolTipRole:
return frame.filePath().isEmpty() ? QVariant() : QVariant(frame.filePath());
default:
return QVariant();
}
const Debugger::DiagnosticLocation location(frame.filePath(), frame.line(), 0);
return Debugger::DetailedErrorView::locationData(role, location);
}
QVariant ErrorItem::data(int column, int role) const
{
if (column == Debugger::DetailedErrorView::LocationColumn) {
const Frame frame = m_model->findRelevantFrame(m_error);
return location(frame, role);
}
if (column == Debugger::DetailedErrorView::LocationColumn)
return locationData(role, m_model->findRelevantFrame(m_error));
// DiagnosticColumn
switch (role) {
@@ -243,7 +235,7 @@ QVariant StackItem::data(int column, int role) const
{
const ErrorItem * const errorItem = getErrorItem();
if (column == Debugger::DetailedErrorView::LocationColumn)
return location(errorItem->modelPrivate()->findRelevantFrame(errorItem->error()), role);
return locationData(role, errorItem->modelPrivate()->findRelevantFrame(errorItem->error()));
// DiagnosticColumn
switch (role) {
@@ -271,7 +263,7 @@ FrameItem::FrameItem(const Frame &frame) : m_frame(frame)
QVariant FrameItem::data(int column, int role) const
{
if (column == Debugger::DetailedErrorView::LocationColumn)
return location(m_frame, role);
return locationData(role, m_frame);
// DiagnosticColumn
switch (role) {

View File

@@ -101,10 +101,10 @@ isEmpty(LLVM_VERSION) {
$$llvmWarningOrError(\
"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")
} else:!versionIsAtLeast($$LLVM_VERSION, 5, 0, 0): {
} else:!versionIsAtLeast($$LLVM_VERSION, 6, 0, 0): {
# CLANG-UPGRADE-CHECK: Adapt minimum version numbers.
$$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 =
} else {
LLVM_LIBDIR = $$quote($$system($$llvm_config --libdir, lines))
@@ -141,11 +141,11 @@ isEmpty(LLVM_VERSION) {
QTC_NO_CLANG_LIBTOOLING=$$(QTC_NO_CLANG_LIBTOOLING)
isEmpty(QTC_NO_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}
LIBTOOLING_LIBS += $$CLANGTOOLING_LIBS $$LLVM_STATIC_LIBS
} 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 {
warning("Clang LibTooling is disabled.")

View File

@@ -163,8 +163,7 @@ static const char *builtinTypeToText(CXTypeKind kind)
// https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html
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
case CXType_Half:

View File

@@ -93,8 +93,6 @@ SourceLocation::SourceLocation(CXTranslationUnit cxTranslationUnit,
return;
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) {
const uint lineStart = offset_ + 1 - column_;
const char *contents = clang_getFileContents(cxTranslationUnit, cxFile, nullptr);
@@ -106,7 +104,6 @@ SourceLocation::SourceLocation(CXTranslationUnit cxTranslationUnit,
column_ = static_cast<uint>(QString::fromUtf8(&contents[lineStart],
static_cast<int>(column_)).size());
}
#endif
}
SourceLocation::SourceLocation(CXTranslationUnit cxTranslationUnit,

View File

@@ -19,7 +19,7 @@ include($$PWD/../../../src/shared/clang/clang_defines.pri)
include($$PWD/../../../src/tools/clangbackend/source/clangbackendclangipc-source.pri)
include($$PWD/../../../src/plugins/clangcodemodel/clangcodemodelunittestfiles.pri)
} else {
DEFINES += CLANG_VERSION=\\\"5.0.0\\\"
DEFINES += CLANG_VERSION=\\\"6.0.0\\\"
DEFINES += "\"CLANG_RESOURCE_DIR=\\\"/usr/include\\\"\""
}

View File

@@ -148,7 +148,7 @@ TEST_F(SkippedSourceRanges, DISABLED_ON_WINDOWS(RangeOne))
{
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));
}
@@ -156,7 +156,7 @@ TEST_F(SkippedSourceRanges, DISABLED_ON_WINDOWS(RangeTwo))
{
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));
}