Skip to content

Commit cf652f5

Browse files
Convert root_cause test to use Clang's built-in diagnostic verifier.
This means we now verify the line numbers of the diagnostics for free, which would have been a pain with the existing CHECK-DAG system. - Make the 3c tool accept a -verify option analogous to that of `clang -cc1` to verify diagnostics against `// expected-warning` comments. Currently, this applies only to the rewriting phase. - Fix a few mistakes in the expected diagnostics in the root_cause test.
1 parent e6d3e06 commit cf652f5

File tree

4 files changed

+59
-29
lines changed

4 files changed

+59
-29
lines changed

clang/include/clang/3C/3C.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ struct _3COptions {
6565
bool RemoveItypes;
6666
bool ForceItypes;
6767
#endif
68+
69+
// Currently applies only to the rewriting phase (because it is the only phase
70+
// that generates diagnostics, except for the declaration merging diagnostics
71+
// that are currently fatal) and uses the default "expected" prefix.
72+
bool VerifyDiagnosticOutput;
6873
};
6974

7075
// The main interface exposed by the 3C to interact with the tool.

clang/lib/3C/3C.cpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ bool DisableCCTypeChecker;
5454
bool WarnRootCause;
5555
bool WarnAllRootCause;
5656
std::set<std::string> FilePaths;
57+
bool VerifyDiagnosticOutput;
5758

5859
#ifdef FIVE_C
5960
bool RemoveItypes;
@@ -95,19 +96,39 @@ class RewriteAction : public ASTFrontendAction {
9596

9697
template <typename T>
9798
std::unique_ptr<FrontendActionFactory>
98-
newFrontendActionFactoryA(ProgramInfo &I) {
99+
newFrontendActionFactoryA(ProgramInfo &I, bool VerifyTheseDiagnostics = false) {
99100
class ArgFrontendActionFactory : public FrontendActionFactory {
100101
public:
101-
explicit ArgFrontendActionFactory(ProgramInfo &I) : Info(I) {}
102+
explicit ArgFrontendActionFactory(ProgramInfo &I,
103+
bool VerifyTheseDiagnostics)
104+
: Info(I), VerifyTheseDiagnostics(VerifyTheseDiagnostics) {}
102105

103106
FrontendAction *create() override { return new T(Info); }
104107

108+
bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
109+
FileManager *Files,
110+
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
111+
DiagnosticConsumer *DiagConsumer) override {
112+
if (VerifyTheseDiagnostics) {
113+
// Mirroring the logic of clang::ParseDiagnosticArgs in
114+
// clang/lib/Frontend/CompilerInvocation.cpp. In particular, note that
115+
// VerifyPrefixes is assumed to be sorted, in case we add more in the
116+
// future.
117+
DiagnosticOptions &DiagOpts = Invocation->getDiagnosticOpts();
118+
DiagOpts.VerifyDiagnostics = true;
119+
DiagOpts.VerifyPrefixes.push_back("expected");
120+
}
121+
return FrontendActionFactory::runInvocation(
122+
Invocation, Files, PCHContainerOps, DiagConsumer);
123+
}
124+
105125
private:
106126
ProgramInfo &Info;
127+
bool VerifyTheseDiagnostics;
107128
};
108129

109130
return std::unique_ptr<FrontendActionFactory>(
110-
new ArgFrontendActionFactory(I));
131+
new ArgFrontendActionFactory(I, VerifyTheseDiagnostics));
111132
}
112133

113134
ArgumentsAdjuster getIgnoreCheckedPointerAdjuster() {
@@ -192,6 +213,7 @@ _3CInterface::_3CInterface(const struct _3COptions &CCopt,
192213
AllocatorFunctions = CCopt.AllocatorFunctions;
193214
WarnRootCause = CCopt.WarnRootCause || CCopt.WarnAllRootCause;
194215
WarnAllRootCause = CCopt.WarnAllRootCause;
216+
VerifyDiagnosticOutput = CCopt.VerifyDiagnosticOutput;
195217

196218
#ifdef FIVE_C
197219
RemoveItypes = CCopt.RemoveItypes;
@@ -368,7 +390,7 @@ bool _3CInterface::writeConvertedFileToDisk(const std::string &FilePath) {
368390
Tool.appendArgumentsAdjuster(getIgnoreCheckedPointerAdjuster());
369391
std::unique_ptr<ToolAction> RewriteTool =
370392
newFrontendActionFactoryA<RewriteAction<RewriteConsumer, ProgramInfo>>(
371-
GlobalProgramInfo);
393+
GlobalProgramInfo, VerifyDiagnosticOutput);
372394

373395
if (RewriteTool) {
374396
int ToolExitCode = Tool.run(RewriteTool.get());
@@ -388,7 +410,7 @@ bool _3CInterface::writeAllConvertedFilesToDisk() {
388410
// Rewrite the input files
389411
std::unique_ptr<ToolAction> RewriteTool =
390412
newFrontendActionFactoryA<RewriteAction<RewriteConsumer, ProgramInfo>>(
391-
GlobalProgramInfo);
413+
GlobalProgramInfo, VerifyDiagnosticOutput);
392414
if (RewriteTool) {
393415
int ToolExitCode = Tool.run(RewriteTool.get());
394416
if (ToolExitCode != 0)

clang/test/3C/root_cause.c

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,43 @@
1-
// RUN: 3c -extra-arg="-Wno-everything" -alltypes -warn-root-cause %s 2>&1 >%t.unused | FileCheck %s
1+
// RUN: 3c -extra-arg="-Wno-everything" -verify -alltypes -warn-root-cause %s
22

33
// This test is unusual in that it checks for the errors in the code
44

55
#include <stddef.h>
66
extern _Itype_for_any(T) void *malloc(size_t size) : itype(_Array_ptr<T>) byte_count(size);
77

8-
void *x;
9-
// CHECK-DAG: Default void* type
8+
void *x; // expected-warning {{Default void* type}}
109

1110
void test0() {
1211
int *a;
1312
char *b;
14-
a = b;
15-
// CHECK-DAG: Cast from int * to char *
13+
a = b; // expected-warning {{Cast from char * to int *}}
1614

1715
int *c;
18-
(char*) c;
19-
// CHECK-DAG: Cast from int * to char *
16+
(char*) c; // expected-warning {{Cast from int * to char *}}
2017

2118

2219
int *e;
2320
char *f;
24-
f = (char*) e;
25-
// CHECK-DAG: Cast from char * to int *
21+
f = (char*) e; // expected-warning {{Cast from int * to char *}}
2622
}
2723

2824
void test1() {
2925
int a;
3026
int *b;
31-
b = malloc(sizeof(int));
27+
b = malloc(sizeof(int)); // expected-warning {{Bad pointer type solution}}
3228
b[0] = 1;
3329

3430
union u {
35-
int *a;
36-
// CHECK-DAG: Union or external struct field encountered
37-
int *b;
38-
// CHECK-DAG: Union or external struct field encountered
31+
int *a; // expected-warning {{Union or external struct field encountered}}
32+
int *b; // expected-warning {{Union or external struct field encountered}}
3933
};
4034

4135
void (*c)(void);
42-
c++;
43-
// CHECK-DAG: Pointer arithmetic performed on a function pointer
36+
c++; // expected-warning {{Pointer arithmetic performed on a function pointer}}
4437

45-
int *d = malloc(1);
46-
// CHECK-DAG: Unsafe call to allocator function
38+
int *d = malloc(1); // expected-warning {{Unsafe call to allocator function}}
4739
}
4840

49-
extern int *glob;
50-
// CHECK-DAG: External global variable glob has no definition
41+
extern int *glob; // expected-warning {{External global variable glob has no definition}}
5142

52-
void (*f)(void *);
53-
// CHECK-DAG: Default void* type
54-
55-
// CHECK-DAG: 11 warnings generated.
43+
void (*f)(void *); // expected-warning {{Default void* type}}

clang/tools/3c/3CStandalone.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,20 @@ static cl::opt<bool>
121121
"even those unlikely to be interesting."),
122122
cl::init(false), cl::cat(_3CCategory));
123123

124+
// https://clang.llvm.org/doxygen/classclang_1_1VerifyDiagnosticConsumer.html#details
125+
//
126+
// Analogous to the -verify option of `clang -cc1`, but currently applies only
127+
// to the rewriting phase (because it is the only phase that generates
128+
// diagnostics, except for the declaration merging diagnostics that are
129+
// currently fatal). No checking of diagnostics from the other phases is
130+
// performed. We cannot simply have the caller pass `-extra-arg=-Xclang
131+
// -extra-arg=-verify` because that would expect each phase to produce the same
132+
// set of diagnostics.
133+
static cl::opt<bool> OptVerifyDiagnosticOutput(
134+
"verify",
135+
cl::desc("Verify diagnostic output (for automated testing of 3C)."),
136+
cl::init(false), cl::cat(_3CCategory), cl::Hidden);
137+
124138
#ifdef FIVE_C
125139
static cl::opt<bool> OptRemoveItypes(
126140
"remove-itypes",
@@ -161,6 +175,7 @@ int main(int argc, const char **argv) {
161175
CcOptions.DisableCCTypeChecker = OptDiableCCTypeChecker;
162176
CcOptions.WarnRootCause = OptWarnRootCause;
163177
CcOptions.WarnAllRootCause = OptWarnAllRootCause;
178+
CcOptions.VerifyDiagnosticOutput = OptVerifyDiagnosticOutput;
164179

165180
#ifdef FIVE_C
166181
CcOptions.RemoveItypes = OptRemoveItypes;

0 commit comments

Comments
 (0)