Skip to content

Commit 974fc45

Browse files
committed
[clang] Fix missing promotion type for opaque enum declarations in class templates
Repeat the steps in `Sema::ActOnTag` for the promotion type after type substitution of the underlying type. This is required in the case of an *opaque-enum-declaration* (see [dcl.enum]). If, instead, a full *enum-specifier* (subsequent curly braces) is provided, `Sema::ActOnEnumBody` is re-invoked on template instantiation overriding the promotion type and hiding the issue. Note that, in contrast to `Sema::ActOnEnumBody`, `Sema::ActOnTag` is *not* called again for the instantiated enumeration type. Fixes #116525.
1 parent 59354a8 commit 974fc45

File tree

1 file changed

+17
-0
lines changed

1 file changed

+17
-0
lines changed

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,6 +1571,23 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
15711571
Enum->setIntegerType(SemaRef.Context.IntTy);
15721572
else
15731573
Enum->setIntegerTypeSourceInfo(NewTI);
1574+
1575+
// The following lines are relevant for opaque-enum-declarations.
1576+
// If users declare a full enum-specifier, the promotion type is reset
1577+
// again when parsing the (potentially empty) enumerator-list.
1578+
// We implement the same logic from C++11 [conv.prom] p4 here but only
1579+
// after template specialization [temp.spec.general] because it requires
1580+
// the concrete type.
1581+
// Note that (1) this also correctly handles the non-dependent case,
1582+
// (2) we set the promotion type for scoped enumerations to ensure
1583+
// consistency with declarations outside of templates, (3) we guarantee a
1584+
// valid promotion even if the user provided an invalid underlying type
1585+
// (fallback to "default int").
1586+
QualType UnderlyingType = Enum->getIntegerType();
1587+
Enum->setPromotionType(
1588+
SemaRef.Context.isPromotableIntegerType(UnderlyingType)
1589+
? SemaRef.Context.getPromotedIntegerType(UnderlyingType)
1590+
: UnderlyingType);
15741591
} else {
15751592
assert(!D->getIntegerType()->isDependentType()
15761593
&& "Dependent type without type source info");

0 commit comments

Comments
 (0)