Skip to content

Commit c86d47b

Browse files
committed
[ASTImporter] Added visibility context check for TypedefNameDecl.
Summary: ASTImporter makes now difference between typedefs and type aliases with same name in different translation units if these are not visible outside. Reviewers: martong, a.sidorin, shafik, a_sidorin Reviewed By: martong, shafik Subscribers: rnkovacs, dkrupp, Szelethus, gamesh411, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D64480 llvm-svn: 370903
1 parent 5309189 commit c86d47b

File tree

2 files changed

+68
-13
lines changed

2 files changed

+68
-13
lines changed

clang/lib/AST/ASTImporter.cpp

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,27 @@ Expected<LambdaCapture> ASTNodeImporter::import(const LambdaCapture &From) {
932932
EllipsisLoc);
933933
}
934934

935+
template <typename T>
936+
bool ASTNodeImporter::hasSameVisibilityContext(T *Found, T *From) {
937+
if (From->hasExternalFormalLinkage())
938+
return Found->hasExternalFormalLinkage();
939+
if (Importer.GetFromTU(Found) != From->getTranslationUnitDecl())
940+
return false;
941+
if (From->isInAnonymousNamespace())
942+
return Found->isInAnonymousNamespace();
943+
else
944+
return !Found->isInAnonymousNamespace() &&
945+
!Found->hasExternalFormalLinkage();
946+
}
947+
948+
template <>
949+
bool ASTNodeImporter::hasSameVisibilityContext(TypedefNameDecl *Found,
950+
TypedefNameDecl *From) {
951+
if (From->isInAnonymousNamespace() && Found->isInAnonymousNamespace())
952+
return Importer.GetFromTU(Found) == From->getTranslationUnitDecl();
953+
return From->isInAnonymousNamespace() == Found->isInAnonymousNamespace();
954+
}
955+
935956
} // namespace clang
936957

937958
//----------------------------------------------------------------------------
@@ -2344,6 +2365,9 @@ ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
23442365
// If this typedef is not in block scope, determine whether we've
23452366
// seen a typedef with the same name (that we can merge with) or any
23462367
// other entity by that name (which name lookup could conflict with).
2368+
// Note: Repeated typedefs are not valid in C99:
2369+
// 'typedef int T; typedef int T;' is invalid
2370+
// We do not care about this now.
23472371
if (!DC->isFunctionOrMethod()) {
23482372
SmallVector<NamedDecl *, 4> ConflictingDecls;
23492373
unsigned IDNS = Decl::IDNS_Ordinary;
@@ -2352,6 +2376,9 @@ ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
23522376
if (!FoundDecl->isInIdentifierNamespace(IDNS))
23532377
continue;
23542378
if (auto *FoundTypedef = dyn_cast<TypedefNameDecl>(FoundDecl)) {
2379+
if (!hasSameVisibilityContext(FoundTypedef, D))
2380+
continue;
2381+
23552382
QualType FromUT = D->getUnderlyingType();
23562383
QualType FoundUT = FoundTypedef->getUnderlyingType();
23572384
if (Importer.IsStructurallyEquivalent(FromUT, FoundUT)) {
@@ -3022,19 +3049,6 @@ Error ASTNodeImporter::ImportFunctionDeclBody(FunctionDecl *FromFD,
30223049
return Error::success();
30233050
}
30243051

3025-
template <typename T>
3026-
bool ASTNodeImporter::hasSameVisibilityContext(T *Found, T *From) {
3027-
if (From->hasExternalFormalLinkage())
3028-
return Found->hasExternalFormalLinkage();
3029-
if (Importer.GetFromTU(Found) != From->getTranslationUnitDecl())
3030-
return false;
3031-
if (From->isInAnonymousNamespace())
3032-
return Found->isInAnonymousNamespace();
3033-
else
3034-
return !Found->isInAnonymousNamespace() &&
3035-
!Found->hasExternalFormalLinkage();
3036-
}
3037-
30383052
ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
30393053

30403054
SmallVector<Decl *, 2> Redecls = getCanonicalForwardRedeclChain(D);

clang/unittests/AST/ASTImporterVisibilityTest.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ struct GetEnumPattern {
3939
using DeclTy = EnumDecl;
4040
BindableMatcher<Decl> operator()() { return enumDecl(hasName("E")); }
4141
};
42+
struct GetTypedefNamePattern {
43+
using DeclTy = TypedefNameDecl;
44+
BindableMatcher<Decl> operator()() { return typedefNameDecl(hasName("T")); }
45+
};
4246

4347
// Values for the value-parameterized test fixtures.
4448
// FunctionDecl:
@@ -55,6 +59,11 @@ const auto *AnonC = "namespace { class X; }";
5559
// EnumDecl:
5660
const auto *ExternE = "enum E {};";
5761
const auto *AnonE = "namespace { enum E {}; }";
62+
// TypedefNameDecl:
63+
const auto *ExternTypedef = "typedef int T;";
64+
const auto *AnonTypedef = "namespace { typedef int T; }";
65+
const auto *ExternUsing = "using T = int;";
66+
const auto *AnonUsing = "namespace { using T = int; }";
5867

5968
// First value in tuple: Compile options.
6069
// Second value in tuple: Source code to be used in the test.
@@ -243,6 +252,7 @@ using ImportFunctionsVisibility = ImportVisibility<GetFunPattern>;
243252
using ImportVariablesVisibility = ImportVisibility<GetVarPattern>;
244253
using ImportClassesVisibility = ImportVisibility<GetClassPattern>;
245254
using ImportEnumsVisibility = ImportVisibility<GetEnumPattern>;
255+
using ImportTypedefNameVisibility = ImportVisibility<GetTypedefNamePattern>;
246256

247257
// FunctionDecl.
248258
TEST_P(ImportFunctionsVisibility, ImportAfter) {
@@ -272,6 +282,13 @@ TEST_P(ImportEnumsVisibility, ImportAfter) {
272282
TEST_P(ImportEnumsVisibility, ImportAfterImport) {
273283
TypedTest_ImportAfterImportWithMerge();
274284
}
285+
// TypedefNameDecl.
286+
TEST_P(ImportTypedefNameVisibility, ImportAfter) {
287+
TypedTest_ImportAfterWithMerge();
288+
}
289+
TEST_P(ImportTypedefNameVisibility, ImportAfterImport) {
290+
TypedTest_ImportAfterImportWithMerge();
291+
}
275292

276293
const bool ExpectLink = true;
277294
const bool ExpectNotLink = false;
@@ -318,6 +335,30 @@ INSTANTIATE_TEST_CASE_P(
318335
std::make_tuple(ExternE, AnonE, ExpectNotLink),
319336
std::make_tuple(AnonE, ExternE, ExpectNotLink),
320337
std::make_tuple(AnonE, AnonE, ExpectNotLink))), );
338+
INSTANTIATE_TEST_CASE_P(
339+
ParameterizedTests, ImportTypedefNameVisibility,
340+
::testing::Combine(
341+
DefaultTestValuesForRunOptions,
342+
::testing::Values(
343+
std::make_tuple(ExternTypedef, ExternTypedef, ExpectLink),
344+
std::make_tuple(ExternTypedef, AnonTypedef, ExpectNotLink),
345+
std::make_tuple(AnonTypedef, ExternTypedef, ExpectNotLink),
346+
std::make_tuple(AnonTypedef, AnonTypedef, ExpectNotLink),
347+
348+
std::make_tuple(ExternUsing, ExternUsing, ExpectLink),
349+
std::make_tuple(ExternUsing, AnonUsing, ExpectNotLink),
350+
std::make_tuple(AnonUsing, ExternUsing, ExpectNotLink),
351+
std::make_tuple(AnonUsing, AnonUsing, ExpectNotLink),
352+
353+
std::make_tuple(ExternUsing, ExternTypedef, ExpectLink),
354+
std::make_tuple(ExternUsing, AnonTypedef, ExpectNotLink),
355+
std::make_tuple(AnonUsing, ExternTypedef, ExpectNotLink),
356+
std::make_tuple(AnonUsing, AnonTypedef, ExpectNotLink),
357+
358+
std::make_tuple(ExternTypedef, ExternUsing, ExpectLink),
359+
std::make_tuple(ExternTypedef, AnonUsing, ExpectNotLink),
360+
std::make_tuple(AnonTypedef, ExternUsing, ExpectNotLink),
361+
std::make_tuple(AnonTypedef, AnonUsing, ExpectNotLink))), );
321362

322363
} // end namespace ast_matchers
323364
} // end namespace clang

0 commit comments

Comments
 (0)