From e62dc1f6252c1dcdcc2a64e8e3b07a32412e9d89 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Fri, 3 Apr 2020 13:42:23 -0700 Subject: [PATCH] [MS] Fix assert handling enum forward decls in hasVisibleDefinition An enum may be considered to be a complete type if it was forward declared. It may be declared with a fixed underlying type, or, in MSVC compatiblity mode, with no type at all. Previously, the code was written with special handling for fixed enums. I generalized the code to check if the underlying integer type is known, which should be the case when targetting the MSVC C++ ABI. Fixes PR45409 --- clang/lib/Sema/SemaType.cpp | 8 ++++---- clang/test/Modules/Inputs/ms-enums/A.h | 1 + clang/test/Modules/Inputs/ms-enums/B.h | 1 + clang/test/Modules/Inputs/ms-enums/module.map | 2 ++ clang/test/Modules/ms-enums.cpp | 12 ++++++++++++ 5 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 clang/test/Modules/Inputs/ms-enums/A.h create mode 100644 clang/test/Modules/Inputs/ms-enums/B.h create mode 100644 clang/test/Modules/Inputs/ms-enums/module.map create mode 100644 clang/test/Modules/ms-enums.cpp diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 49a5dcb..020e39f 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -8060,10 +8060,10 @@ bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested, } else if (auto *ED = dyn_cast(D)) { if (auto *Pattern = ED->getTemplateInstantiationPattern()) ED = Pattern; - if (OnlyNeedComplete && ED->isFixed()) { - // If the enum has a fixed underlying type, and we're only looking for a - // complete type (not a definition), any visible declaration of it will - // do. + if (OnlyNeedComplete && !ED->getIntegerType().isNull()) { + // If the enum has an integer type, it may have been forward declared. + // Since we're only looking for a complete type (not a definition), any + // visible declaration of it will do. *Suggested = nullptr; for (auto *Redecl : ED->redecls()) { if (isVisible(Redecl)) diff --git a/clang/test/Modules/Inputs/ms-enums/A.h b/clang/test/Modules/Inputs/ms-enums/A.h new file mode 100644 index 0000000..1684452 --- /dev/null +++ b/clang/test/Modules/Inputs/ms-enums/A.h @@ -0,0 +1 @@ +enum fwd_enum; diff --git a/clang/test/Modules/Inputs/ms-enums/B.h b/clang/test/Modules/Inputs/ms-enums/B.h new file mode 100644 index 0000000..7a13ba4 --- /dev/null +++ b/clang/test/Modules/Inputs/ms-enums/B.h @@ -0,0 +1 @@ +#include "A.h" diff --git a/clang/test/Modules/Inputs/ms-enums/module.map b/clang/test/Modules/Inputs/ms-enums/module.map new file mode 100644 index 0000000..d9aed01 --- /dev/null +++ b/clang/test/Modules/Inputs/ms-enums/module.map @@ -0,0 +1,2 @@ +module A { header "A.h" } +module B { header "B.h" } diff --git a/clang/test/Modules/ms-enums.cpp b/clang/test/Modules/ms-enums.cpp new file mode 100644 index 0000000..b3a377c --- /dev/null +++ b/clang/test/Modules/ms-enums.cpp @@ -0,0 +1,12 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -fms-compatibility -x c++ -std=c++20 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/ms-enums %s -verify -fno-modules-error-recovery + +#include "B.h" +// expected-note@A.h:1 {{previous declaration is here}} +// expected-note@A.h:1 2 {{previous definition is here}} + +fwd_enum gv_enum; // expected-error {{must be imported}} + +struct Foo { + enum fwd_enum enum_field; // expected-error 2 {{must be imported}} +}; -- 2.7.4