Skip to content

Commit 413e7db

Browse files
committed
[ClangImporter] Handle diagnostics about cast types in macros
The importer handles these by first trying to look up the type by name using Clang's Sema, but that lookup can cause diagnostics to be emitted (usually availability diagnostics). We could try to figure out how to propagate that to the macro when we import it, but for now just drop the macro instead if there are any diagnostics emitted when looking up the type. This will be a small source compatibility break if anyone was using a macro defined in terms of a type that's deprecated or that has partial availability; the macro will now silently not be imported instead of producing an unsilenceable warning. rdar://problem/36528212
1 parent 309ae61 commit 413e7db

File tree

3 files changed

+23
-1
lines changed

3 files changed

+23
-1
lines changed

lib/ClangImporter/ImportMacro.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "clang/AST/Expr.h"
2222
#include "clang/Lex/MacroInfo.h"
2323
#include "clang/Lex/Preprocessor.h"
24+
#include "clang/Sema/DelayedDiagnostic.h"
2425
#include "clang/Sema/Sema.h"
2526
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
2627
#include "swift/AST/ASTContext.h"
@@ -361,10 +362,16 @@ static ValueDecl *importMacro(ClangImporter::Implementation &impl,
361362
}
362363
auto identifierName = identifierInfo->getName();
363364
auto &identifier = impl.getClangASTContext().Idents.get(identifierName);
365+
366+
clang::sema::DelayedDiagnosticPool diagPool{
367+
impl.getClangSema().DelayedDiagnostics.getCurrentPool()};
368+
auto diagState = impl.getClangSema().DelayedDiagnostics.push(diagPool);
364369
auto parsedType = impl.getClangSema().getTypeName(identifier,
365370
clang::SourceLocation(),
366371
/*scope*/nullptr);
367-
if (parsedType) {
372+
impl.getClangSema().DelayedDiagnostics.popWithoutEmitting(diagState);
373+
374+
if (parsedType && diagPool.empty()) {
368375
castType = parsedType.get();
369376
} else {
370377
return nullptr;

test/ClangImporter/macros.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,9 @@ func testRecursion() {
172172
_ = RECURSION_IN_EXPR2 // expected-error {{use of unresolved identifier 'RECURSION_IN_EXPR2'}}
173173
_ = RECURSION_IN_EXPR3 // expected-error {{use of unresolved identifier 'RECURSION_IN_EXPR3'}}
174174
}
175+
176+
func testNulls() {
177+
let _: Int = UNAVAILABLE_ONE // expected-error {{use of unresolved identifier 'UNAVAILABLE_ONE'}}
178+
let _: Int = DEPRECATED_ONE // expected-error {{use of unresolved identifier 'DEPRECATED_ONE'}}
179+
let _: Int = OKAY_TYPED_ONE // expected-error {{cannot convert value of type 'okay_t' (aka 'UInt32') to specified type 'Int'}}
180+
}

test/Inputs/clang-importer-sdk/usr/include/macros.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,12 @@
144144

145145
#define RECURSION_WITH_EXPR3 RECURSION_WITH_EXPR3_HELPER + 1
146146
#define RECURSION_WITH_EXPR3_HELPER RECURSION_WITH_EXPR3 + 1
147+
148+
149+
// Casts with problematic types
150+
#define UNAVAILABLE_ONE ((unavailable_t)1)
151+
typedef unsigned unavailable_t __attribute__((unavailable));
152+
#define DEPRECATED_ONE ((deprecated_t)1)
153+
typedef unsigned deprecated_t __attribute__((deprecated));
154+
#define OKAY_TYPED_ONE ((okay_t)1)
155+
typedef unsigned okay_t;

0 commit comments

Comments
 (0)