Merge remote-tracking branch 'origin/swift-3.1-branch' into stable
* origin/swift-3.1-branch:
[docs] Touch up the code coverage doc
[Driver] Report invalid -mtune/-mcpu parameters when -arch=arm64
[Coverage] Suppress creating a code region if the same area is covered by an expansion region.
[test] Pass a fake libLTO.dylib to a driver test which depends on it
[Coverage] Prevent creating a redundant counter if a nested body ends with a macro.
[AST] Make InitListExpr::isExplicit const (NFC)
[AST] Remove unused function, to silence a GCC7 warning.
diff --git a/docs/SourceBasedCodeCoverage.rst b/docs/SourceBasedCodeCoverage.rst
index 8c4ab8d..f2f3f82 100644
--- a/docs/SourceBasedCodeCoverage.rst
+++ b/docs/SourceBasedCodeCoverage.rst
@@ -125,24 +125,24 @@
.. code-block:: none
- 20| 1|#define BAR(x) ((x) || (x))
+ 1| 20|#define BAR(x) ((x) || (x))
^20 ^2
2| 2|template <typename T> void foo(T x) {
- 22| 3| for (unsigned I = 0; I < 10; ++I) { BAR(I); }
+ 3| 22| for (unsigned I = 0; I < 10; ++I) { BAR(I); }
^22 ^20 ^20^20
- 2| 4|}
+ 4| 2|}
------------------
| void foo<int>(int):
- | 1| 2|template <typename T> void foo(T x) {
- | 11| 3| for (unsigned I = 0; I < 10; ++I) { BAR(I); }
+ | 2| 1|template <typename T> void foo(T x) {
+ | 3| 11| for (unsigned I = 0; I < 10; ++I) { BAR(I); }
| ^11 ^10 ^10^10
- | 1| 4|}
+ | 4| 1|}
------------------
| void foo<float>(int):
- | 1| 2|template <typename T> void foo(T x) {
- | 11| 3| for (unsigned I = 0; I < 10; ++I) { BAR(I); }
+ | 2| 1|template <typename T> void foo(T x) {
+ | 3| 11| for (unsigned I = 0; I < 10; ++I) { BAR(I); }
| ^11 ^10 ^10^10
- | 1| 4|}
+ | 4| 1|}
------------------
It's possible to generate a file-level summary of coverage statistics (instead
@@ -177,6 +177,26 @@
% llvm-profdata merge -sparse foo1.profraw foo2.profdata -o foo3.profdata
+Interpreting reports
+====================
+
+There are four statistics tracked in a coverage summary:
+
+* Function coverage is the percentage of functions which have been executed at
+ least once. A function is treated as having been executed if any of its
+ instantiations are executed.
+
+* Instantiation coverage is the percentage of function instantiations which
+ have been executed at least once.
+
+* Line coverage is the percentage of code lines which have been executed at
+ least once.
+
+* Region coverage is the percentage of code regions which have been executed at
+ least once. A code region may span multiple lines (e.g a large function with
+ no control flow). However, it's also possible for a single line to contain
+ multiple code regions (e.g some short-circuited logic).
+
Format compatibility guarantees
===============================
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 9179c77..7f98f00 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -3862,7 +3862,7 @@
// Explicit InitListExpr's originate from source code (and have valid source
// locations). Implicit InitListExpr's are created by the semantic analyzer.
- bool isExplicit() {
+ bool isExplicit() const {
return LBraceLoc.isValid() && RBraceLoc.isValid();
}
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index cff8369..9aead7b 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -93,10 +93,6 @@
VisitStmt(S);
}
-void StmtProfiler::VisitSwitchCase(const SwitchCase *S) {
- VisitStmt(S);
-}
-
void StmtProfiler::VisitCaseStmt(const CaseStmt *S) {
VisitStmt(S);
}
diff --git a/lib/CodeGen/CoverageMappingGen.cpp b/lib/CodeGen/CoverageMappingGen.cpp
index da6fa2a..e008f44 100644
--- a/lib/CodeGen/CoverageMappingGen.cpp
+++ b/lib/CodeGen/CoverageMappingGen.cpp
@@ -92,6 +92,14 @@
/// \brief The source mapping regions for this function.
std::vector<SourceMappingRegion> SourceRegions;
+ /// \brief A set of regions which can be used as a filter.
+ ///
+ /// It is produced by emitExpansionRegions() and is used in
+ /// emitSourceRegions() to suppress producing code regions if
+ /// the same area is covered by expansion regions.
+ typedef llvm::SmallSet<std::pair<SourceLocation, SourceLocation>, 8>
+ SourceRegionFilter;
+
CoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
const LangOptions &LangOpts)
: CVM(CVM), SM(SM), LangOpts(LangOpts) {}
@@ -249,7 +257,7 @@
/// \brief Generate the coverage counter mapping regions from collected
/// source regions.
- void emitSourceRegions() {
+ void emitSourceRegions(const SourceRegionFilter &Filter) {
for (const auto &Region : SourceRegions) {
assert(Region.hasEndLoc() && "incomplete region");
@@ -269,6 +277,13 @@
assert(SM.isWrittenInSameFile(LocStart, LocEnd) &&
"region spans multiple files");
+ // Don't add code regions for the area covered by expansion regions.
+ // This not only suppresses redundant regions, but sometimes prevents
+ // creating regions with wrong counters if, for example, a statement's
+ // body ends at the end of a nested macro.
+ if (Filter.count(std::make_pair(LocStart, LocEnd)))
+ continue;
+
// Find the spilling locations for the mapping region.
unsigned LineStart = SM.getSpellingLineNumber(LocStart);
unsigned ColumnStart = SM.getSpellingColumnNumber(LocStart);
@@ -283,7 +298,8 @@
}
/// \brief Generate expansion regions for each virtual file we've seen.
- void emitExpansionRegions() {
+ SourceRegionFilter emitExpansionRegions() {
+ SourceRegionFilter Filter;
for (const auto &FM : FileIDMapping) {
SourceLocation ExpandedLoc = FM.second.second;
SourceLocation ParentLoc = getIncludeOrExpansionLoc(ExpandedLoc);
@@ -299,6 +315,7 @@
SourceLocation LocEnd = getPreciseTokenLocEnd(ParentLoc);
assert(SM.isWrittenInSameFile(ParentLoc, LocEnd) &&
"region spans multiple files");
+ Filter.insert(std::make_pair(ParentLoc, LocEnd));
unsigned LineStart = SM.getSpellingLineNumber(ParentLoc);
unsigned ColumnStart = SM.getSpellingColumnNumber(ParentLoc);
@@ -309,6 +326,7 @@
*ParentFileID, *ExpandedFileID, LineStart, ColumnStart, LineEnd,
ColumnEnd));
}
+ return Filter;
}
};
@@ -350,7 +368,7 @@
void write(llvm::raw_ostream &OS) {
SmallVector<unsigned, 16> FileIDMapping;
gatherFileIDs(FileIDMapping);
- emitSourceRegions();
+ emitSourceRegions(SourceRegionFilter());
if (MappingRegions.empty())
return;
@@ -432,7 +450,8 @@
SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc);
assert(SM.isWrittenInSameFile(NestedLoc, EndLoc));
- SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc);
+ if (!isRegionAlreadyAdded(NestedLoc, EndLoc))
+ SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc);
EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc));
if (EndLoc.isInvalid())
@@ -604,8 +623,8 @@
void write(llvm::raw_ostream &OS) {
llvm::SmallVector<unsigned, 8> VirtualFileMapping;
gatherFileIDs(VirtualFileMapping);
- emitSourceRegions();
- emitExpansionRegions();
+ SourceRegionFilter Filter = emitExpansionRegions();
+ emitSourceRegions(Filter);
gatherSkippedRegions();
if (MappingRegions.empty())
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index e59119a..758fbe5 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -1140,9 +1140,9 @@
// ARM tools end.
/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are
-/// targeting.
-static std::string getAArch64TargetCPU(const ArgList &Args) {
- Arg *A;
+/// targeting. Set \p A to the Arg corresponding to the -mcpu or -mtune
+/// arguments if they are provided, or to nullptr otherwise.
+static std::string getAArch64TargetCPU(const ArgList &Args, Arg *&A) {
std::string CPU;
// If we have -mtune or -mcpu, use that.
if ((A = Args.getLastArg(options::OPT_mtune_EQ))) {
@@ -1919,13 +1919,15 @@
static std::string getCPUName(const ArgList &Args, const llvm::Triple &T,
bool FromAs = false) {
+ Arg *A;
+
switch (T.getArch()) {
default:
return "";
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
- return getAArch64TargetCPU(Args);
+ return getAArch64TargetCPU(Args, A);
case llvm::Triple::arm:
case llvm::Triple::armeb:
@@ -2443,8 +2445,8 @@
else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))
success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
else if (Args.hasArg(options::OPT_arch))
- success = getAArch64ArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args), Args,
- Features);
+ success = getAArch64ArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args, A),
+ Args, Features);
if (success && (A = Args.getLastArg(options::OPT_mtune_EQ)))
success =
@@ -2452,9 +2454,9 @@
else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ)))
success =
getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
- else if (Args.hasArg(options::OPT_arch))
- success = getAArch64MicroArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args),
- Args, Features);
+ else if (success && Args.hasArg(options::OPT_arch))
+ success = getAArch64MicroArchFeaturesFromMcpu(
+ D, getAArch64TargetCPU(Args, A), Args, Features);
if (!success)
D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
diff --git a/test/CoverageMapping/macroception.c b/test/CoverageMapping/macroception.c
index 7848741..7c142ef 100644
--- a/test/CoverageMapping/macroception.c
+++ b/test/CoverageMapping/macroception.c
@@ -11,7 +11,6 @@
int main() M1
return 0;
}
-// CHECK-NEXT: File 1, 4:12 -> 4:14 = #0
// CHECK-NEXT: Expansion,File 1, 4:12 -> 4:14 = #0
// CHECK-NEXT: File 2, 3:12 -> 3:13 = #0
@@ -21,7 +20,6 @@
void func2() {
int x = 0;
M11
-// CHECK-NEXT: File 1, 6:13 -> 6:16 = #0
// CHECK-NEXT: Expansion,File 1, 6:13 -> 6:16 = #0
// CHECK-NEXT: File 2, 5:13 -> 5:14 = #0
@@ -32,9 +30,7 @@
void func3() M1
int x = 0;
M11
-// CHECK-NEXT: File 1, 4:12 -> 4:14 = #0
// CHECK-NEXT: Expansion,File 1, 4:12 -> 4:14 = #0
-// CHECK-NEXT: File 2, 6:13 -> 6:16 = #0
// CHECK-NEXT: Expansion,File 2, 6:13 -> 6:16 = #0
// CHECK-NEXT: File 3, 3:12 -> 3:13 = #0
// CHECK-NEXT: File 4, 5:13 -> 5:14 = #0
@@ -44,9 +40,7 @@
// CHECK-NEXT: File 0, [[@LINE+2]]:16 -> [[@LINE+2]]:20 = #0
// CHECK-NEXT: Expansion,File 0, [[@LINE+1]]:17 -> [[@LINE+1]]:20 = #0
void func4() M1 M11
-// CHECK-NEXT: File 1, 4:12 -> 4:14 = #0
// CHECK-NEXT: Expansion,File 1, 4:12 -> 4:14 = #0
-// CHECK-NEXT: File 2, 6:13 -> 6:16 = #0
// CHECK-NEXT: Expansion,File 2, 6:13 -> 6:16 = #0
// CHECK-NEXT: File 3, 3:12 -> 3:13 = #0
// CHECK-NEXT: File 4, 5:13 -> 5:14 = #0
diff --git a/test/CoverageMapping/macros.c b/test/CoverageMapping/macros.c
index f633961..60164be 100644
--- a/test/CoverageMapping/macros.c
+++ b/test/CoverageMapping/macros.c
@@ -3,6 +3,7 @@
#define MACRO return; bar()
#define MACRO_2 bar()
#define MACRO_1 return; MACRO_2
+#define MACRO_3 MACRO_2
void bar() {}
@@ -24,7 +25,6 @@
i = 2;
}
// CHECK-NEXT: File 1, 5:17 -> 5:32 = #0
-// CHECK-NEXT: File 1, 5:25 -> 5:32 = 0
// CHECK-NEXT: Expansion,File 1, 5:25 -> 5:32 = 0
// CHECK-NEXT: File 2, 4:17 -> 4:22 = 0
@@ -36,8 +36,29 @@
// CHECK-NEXT: File 1, 4:17 -> 4:22 = #0
// CHECK-NEXT: File 2, 4:17 -> 4:22 = #0
+// CHECK-NEXT: func4
+void func4() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+6]]:2 = #0
+ int i = 0;
+ while (i++ < 10) // CHECK-NEXT: File 0, [[@LINE]]:10 -> [[@LINE]]:18 = (#0 + #1)
+ if (i < 5) // CHECK-NEXT: File 0, [[@LINE]]:5 -> [[@LINE+2]]:14 = #1
+ // CHECK-NEXT: File 0, [[@LINE-1]]:9 -> [[@LINE-1]]:14 = #1
+ MACRO_2; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:7 -> [[@LINE]]:14 = #2
+}
+// CHECK-NEXT: File 1, 4:17 -> 4:22 = #2
+// CHECK-NOT: File 1
+
+// CHECK-NEXT: func5
+void func5() { // CHECK-NEXT: File 0, [[@LINE]]:14 -> [[@LINE+4]]:2 = #0
+ int i = 0;
+ if (i > 5) // CHECK-NEXT: File 0, [[@LINE]]:7 -> [[@LINE]]:12 = #0
+ MACRO_3; // CHECK-NEXT: Expansion,File 0, [[@LINE]]:5 -> [[@LINE]]:12 = #1
+}
+// CHECK-NEXT: Expansion,File 1, 6:17 -> 6:24 = #1
+// CHECK-NEXT: File 2, 4:17 -> 4:22 = #1
+
int main(int argc, const char *argv[]) {
func();
func2();
func3();
+ func4();
}
diff --git a/test/Driver/arm-cortex-cpus.c b/test/Driver/arm-cortex-cpus.c
index 5bf8939..ca04f11 100644
--- a/test/Driver/arm-cortex-cpus.c
+++ b/test/Driver/arm-cortex-cpus.c
@@ -303,7 +303,10 @@
// ================== Check that a bogus CPU gives an error
// RUN: %clang -target arm -mcpu=bogus -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BOGUS-CPU %s
+// RUN: %clang -target armv8-apple-darwin -arch arm64 -mcpu=bogus -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BOGUS-CPU %s
// CHECK-BOGUS-CPU: error: {{.*}} does not support '-mcpu=bogus'
+// RUN: %clang -target armv8-apple-darwin -arch arm64 -mtune=bogus -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BOGUS-TUNE %s
+// CHECK-BOGUS-TUNE: error: {{.*}} does not support '-mtune=bogus'
// ================== Check default Architecture on each ARM11 CPU
// RUN: %clang -target arm-linux-gnueabi -mcpu=arm1136j-s -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV6 %s
diff --git a/test/Driver/darwin-ld-lto.c b/test/Driver/darwin-ld-lto.c
index 23e006a..06152ac 100644
--- a/test/Driver/darwin-ld-lto.c
+++ b/test/Driver/darwin-ld-lto.c
@@ -2,24 +2,24 @@
// Check that ld gets "-lto_library" and warnings about libLTO.dylib path.
+// RUN: mkdir -p %T/bin
+// RUN: mkdir -p %T/lib
+// RUN: touch %T/lib/libLTO.dylib
// RUN: %clang -target x86_64-apple-darwin10 -### %s \
-// RUN: -mlinker-version=133 -flto 2> %t.log
-// RUN: cat %t.log
-// RUN: FileCheck -check-prefix=LINK_LTOLIB_PATH %s < %t.log
+// RUN: -ccc-install-dir %T/bin -mlinker-version=133 -flto 2> %t.log
+// RUN: FileCheck -check-prefix=LINK_LTOLIB_PATH %s -input-file %t.log
//
// LINK_LTOLIB_PATH: {{ld(.exe)?"}}
// LINK_LTOLIB_PATH: "-lto_library"
// RUN: %clang -target x86_64-apple-darwin10 -### %s \
// RUN: -ccc-install-dir %S/dummytestdir -mlinker-version=133 -flto 2> %t.log
-// RUN: cat %t.log
-// RUN: FileCheck -check-prefix=LINK_LTOLIB_PATH_WRN %s < %t.log
+// RUN: FileCheck -check-prefix=LINK_LTOLIB_PATH_WRN %s -input-file %t.log
//
// LINK_LTOLIB_PATH_WRN: warning: libLTO.dylib relative to clang installed dir not found; using 'ld' default search path instead
// RUN: %clang -target x86_64-apple-darwin10 -### %s \
// RUN: -ccc-install-dir %S/dummytestdir -mlinker-version=133 -Wno-liblto -flto 2> %t.log
-// RUN: cat %t.log
-// RUN: FileCheck -check-prefix=LINK_LTOLIB_PATH_NOWRN %s < %t.log
+// RUN: FileCheck -check-prefix=LINK_LTOLIB_PATH_NOWRN %s -input-file %t.log
//
// LINK_LTOLIB_PATH_NOWRN-NOT: warning: libLTO.dylib relative to clang installed dir not found; using 'ld' default search path instead