llvm-project/clang/lib/AST/TemplateBase.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

788 lines
24 KiB
C++
Raw Normal View History

//===- TemplateBase.cpp - Common template AST class implementation --------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements common classes used throughout C++ template
// representations.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/TemplateBase.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DependenceFlags.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <optional>
using namespace clang;
/// Print a template integral argument value.
///
/// \param TemplArg the TemplateArgument instance to print.
///
/// \param Out the raw_ostream instance to use for printing.
///
/// \param Policy the printing policy for EnumConstantDecl printing.
///
/// \param IncludeType If set, ensure that the type of the expression printed
/// matches the type of the template argument.
static void printIntegral(const TemplateArgument &TemplArg, raw_ostream &Out,
const PrintingPolicy &Policy, bool IncludeType) {
const Type *T = TemplArg.getIntegralType().getTypePtr();
const llvm::APSInt &Val = TemplArg.getAsIntegral();
if (Policy.UseEnumerators) {
if (const EnumType *ET = T->getAs<EnumType>()) {
for (const EnumConstantDecl *ECD : ET->getDecl()->enumerators()) {
// In Sema::CheckTemplateArugment, enum template arguments value are
// extended to the size of the integer underlying the enum type. This
// may create a size difference between the enum value and template
// argument value, requiring isSameValue here instead of operator==.
if (llvm::APSInt::isSameValue(ECD->getInitVal(), Val)) {
ECD->printQualifiedName(Out, Policy);
return;
}
}
}
}
if (Policy.MSVCFormatting)
IncludeType = false;
if (T->isBooleanType()) {
if (!Policy.MSVCFormatting)
Out << (Val.getBoolValue() ? "true" : "false");
else
Out << Val;
} else if (T->isCharType()) {
if (IncludeType) {
if (T->isSpecificBuiltinType(BuiltinType::SChar))
Out << "(signed char)";
else if (T->isSpecificBuiltinType(BuiltinType::UChar))
Out << "(unsigned char)";
}
CharacterLiteral::print(Val.getZExtValue(), CharacterLiteralKind::Ascii,
Out);
} else if (T->isAnyCharacterType() && !Policy.MSVCFormatting) {
CharacterLiteralKind Kind;
if (T->isWideCharType())
Kind = CharacterLiteralKind::Wide;
else if (T->isChar8Type())
Kind = CharacterLiteralKind::UTF8;
else if (T->isChar16Type())
Kind = CharacterLiteralKind::UTF16;
else if (T->isChar32Type())
Kind = CharacterLiteralKind::UTF32;
else
Kind = CharacterLiteralKind::Ascii;
CharacterLiteral::print(Val.getExtValue(), Kind, Out);
} else if (IncludeType) {
if (const auto *BT = T->getAs<BuiltinType>()) {
switch (BT->getKind()) {
case BuiltinType::ULongLong:
Out << Val << "ULL";
break;
case BuiltinType::LongLong:
Out << Val << "LL";
break;
case BuiltinType::ULong:
Out << Val << "UL";
break;
case BuiltinType::Long:
Out << Val << "L";
break;
case BuiltinType::UInt:
Out << Val << "U";
break;
case BuiltinType::Int:
Out << Val;
break;
default:
Out << "(" << T->getCanonicalTypeInternal().getAsString(Policy) << ")"
<< Val;
break;
}
} else
Out << "(" << T->getCanonicalTypeInternal().getAsString(Policy) << ")"
<< Val;
} else
Out << Val;
}
static unsigned getArrayDepth(QualType type) {
unsigned count = 0;
while (const auto *arrayType = type->getAsArrayTypeUnsafe()) {
count++;
type = arrayType->getElementType();
}
return count;
}
static bool needsAmpersandOnTemplateArg(QualType paramType, QualType argType) {
// Generally, if the parameter type is a pointer, we must be taking the
// address of something and need a &. However, if the argument is an array,
// this could be implicit via array-to-pointer decay.
if (!paramType->isPointerType())
return paramType->isMemberPointerType();
if (argType->isArrayType())
return getArrayDepth(argType) == getArrayDepth(paramType->getPointeeType());
return true;
}
//===----------------------------------------------------------------------===//
// TemplateArgument Implementation
//===----------------------------------------------------------------------===//
[c++20] P1907R1: Support for generalized non-type template arguments of scalar type. (#78041) Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and reverted because a dependency commit was reverted, then committed again as 4b574008aef5a7235c1f894ab065fe300d26e786 and reverted again because "dependency commit" 5a391d38ac6c561ba908334d427f26124ed9132e was reverted. But it doesn't seem that 5a391d38ac6c was a real dependency for this. This commit incorporates 4b574008aef5a7235c1f894ab065fe300d26e786 and 18e093faf726d15f210ab4917142beec51848258 by Richard Smith (@zygoloid), with some minor fixes, most notably: - `UncommonValue` renamed to `StructuralValue` - `VK_PRValue` instead of `VK_RValue` as default kind in lvalue and member pointer handling branch in `BuildExpressionFromNonTypeTemplateArgumentValue`; - handling of `StructuralValue` in `IsTypeDeclaredInsideVisitor`; - filling in `SugaredConverted` along with `CanonicalConverted` parameter in `Sema::CheckTemplateArgument`; - minor cleanup in `TemplateInstantiator::transformNonTypeTemplateParmRef`; - `TemplateArgument` constructors refactored; - `ODRHash` calculation for `UncommonValue`; - USR generation for `UncommonValue`; - more correct MS compatibility mangling algorithm (tested on MSVC ver. 19.35; toolset ver. 143); - IR emitting fixed on using a subobject as a template argument when the corresponding template parameter is used in an lvalue context; - `noundef` attribute and opaque pointers in `template-arguments` test; - analysis for C++17 mode is turned off for templates in `warn-bool-conversion` test; in C++17 and C++20 mode, array reference used as a template argument of pointer type produces template argument of UncommonValue type, and `BuildExpressionFromNonTypeTemplateArgumentValue` makes `OpaqueValueExpr` for it, and `DiagnoseAlwaysNonNullPointer` cannot see through it; despite of "These cases should not warn" comment, I'm not sure about correct behavior; I'd expect a suggestion to replace `if` by `if constexpr`; - `temp.arg.nontype/p1.cpp` and `dr18xx.cpp` tests fixed.
2024-01-21 23:28:57 +03:00
void TemplateArgument::initFromType(QualType T, bool IsNullPtr,
bool IsDefaulted) {
TypeOrValue.Kind = IsNullPtr ? NullPtr : Type;
TypeOrValue.IsDefaulted = IsDefaulted;
TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
}
void TemplateArgument::initFromDeclaration(ValueDecl *D, QualType QT,
bool IsDefaulted) {
assert(D && "Expected decl");
DeclArg.Kind = Declaration;
DeclArg.IsDefaulted = IsDefaulted;
DeclArg.QT = QT.getAsOpaquePtr();
DeclArg.D = D;
}
void TemplateArgument::initFromIntegral(const ASTContext &Ctx,
const llvm::APSInt &Value,
QualType Type, bool IsDefaulted) {
Integer.Kind = Integral;
[clang][TemplateBase] Add IsDefaulted bit to TemplateArgument **Summary** This patch adds a `IsDefaulted` field to `clang::TemplateArgument`. To prevent memory footprint increase we still 1 bit from `ArgKind`. **Changes** 1. `getIsDefaulted`/`setIsDefaulted` to allow clients to communicate an argument's defaulted-ness to the TypePrinter 2. The `TemplateArgument` properties description had to be changed to make sure we correctly mark the defaulted-ness of arguments that came from a deserialized AST (caught by the HLSL test-suite) 3. The `TemplateArgument` constructors now accept a `IsDefaulted` parameter to simplify construction from the tablegen description. Though if people don't want to clutter the constructors we can instead call `setIsDefaulted` from tablegen 4. When `clang::Sema` checks the template arguments against template parameters we now call `setIsDefaulted`. This makes sure that whenever a specialization decl gets constructed, the defaulted-ness of the associated `TemplateArgument`s has already been deduced. This preserves the immutability of `TemplateArgumentList`s **Background** In LLDB we construct ASTs from debug-info and hand it to clang to perform actions such as printing/formatting a typenames. Some debug formats, specifically DWARF, may only encode information about class template instantiations, losing the structure of the generic class definition. However, the `clang::TypePrinter` needs a properly constructed `ClassTemplateDecl` with generic default argument decls to be able to deduce whether a `ClassTemplateSpecializationDecl` was instantiatiated with `TemplateArgument`s that correspond to the defaults. LLDB does know whether a particular template argument was defaulted, but can't currently tell clang about it. This patch allows LLDB to set the defaulted-ness of a `TemplateArgument` and thus benefit more from `clang::TypePrinter`. See discussion in https://reviews.llvm.org/D140423 **Testing** * Added unit-test * LLDB/clang/llvm test-suite passes Differential Revision: https://reviews.llvm.org/D141826
2023-01-15 03:36:50 +00:00
Integer.IsDefaulted = IsDefaulted;
// Copy the APSInt value into our decomposed form.
Integer.BitWidth = Value.getBitWidth();
Integer.IsUnsigned = Value.isUnsigned();
// If the value is large, we have to get additional memory from the ASTContext
unsigned NumWords = Value.getNumWords();
if (NumWords > 1) {
void *Mem = Ctx.Allocate(NumWords * sizeof(uint64_t));
std::memcpy(Mem, Value.getRawData(), NumWords * sizeof(uint64_t));
Integer.pVal = static_cast<uint64_t *>(Mem);
} else {
Integer.VAL = Value.getZExtValue();
}
Integer.Type = Type.getAsOpaquePtr();
}
[c++20] P1907R1: Support for generalized non-type template arguments of scalar type. (#78041) Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and reverted because a dependency commit was reverted, then committed again as 4b574008aef5a7235c1f894ab065fe300d26e786 and reverted again because "dependency commit" 5a391d38ac6c561ba908334d427f26124ed9132e was reverted. But it doesn't seem that 5a391d38ac6c was a real dependency for this. This commit incorporates 4b574008aef5a7235c1f894ab065fe300d26e786 and 18e093faf726d15f210ab4917142beec51848258 by Richard Smith (@zygoloid), with some minor fixes, most notably: - `UncommonValue` renamed to `StructuralValue` - `VK_PRValue` instead of `VK_RValue` as default kind in lvalue and member pointer handling branch in `BuildExpressionFromNonTypeTemplateArgumentValue`; - handling of `StructuralValue` in `IsTypeDeclaredInsideVisitor`; - filling in `SugaredConverted` along with `CanonicalConverted` parameter in `Sema::CheckTemplateArgument`; - minor cleanup in `TemplateInstantiator::transformNonTypeTemplateParmRef`; - `TemplateArgument` constructors refactored; - `ODRHash` calculation for `UncommonValue`; - USR generation for `UncommonValue`; - more correct MS compatibility mangling algorithm (tested on MSVC ver. 19.35; toolset ver. 143); - IR emitting fixed on using a subobject as a template argument when the corresponding template parameter is used in an lvalue context; - `noundef` attribute and opaque pointers in `template-arguments` test; - analysis for C++17 mode is turned off for templates in `warn-bool-conversion` test; in C++17 and C++20 mode, array reference used as a template argument of pointer type produces template argument of UncommonValue type, and `BuildExpressionFromNonTypeTemplateArgumentValue` makes `OpaqueValueExpr` for it, and `DiagnoseAlwaysNonNullPointer` cannot see through it; despite of "These cases should not warn" comment, I'm not sure about correct behavior; I'd expect a suggestion to replace `if` by `if constexpr`; - `temp.arg.nontype/p1.cpp` and `dr18xx.cpp` tests fixed.
2024-01-21 23:28:57 +03:00
void TemplateArgument::initFromStructural(const ASTContext &Ctx, QualType Type,
const APValue &V, bool IsDefaulted) {
Value.Kind = StructuralValue;
Value.IsDefaulted = IsDefaulted;
Value.Value = new (Ctx) APValue(V);
Ctx.addDestruction(Value.Value);
Value.Type = Type.getAsOpaquePtr();
}
TemplateArgument::TemplateArgument(const ASTContext &Ctx,
const llvm::APSInt &Value, QualType Type,
bool IsDefaulted) {
initFromIntegral(Ctx, Value, Type, IsDefaulted);
}
static const ValueDecl *getAsSimpleValueDeclRef(const ASTContext &Ctx,
QualType T, const APValue &V) {
// Pointers to members are relatively easy.
if (V.isMemberPointer() && V.getMemberPointerPath().empty())
return V.getMemberPointerDecl();
// We model class non-type template parameters as their template parameter
// object declaration.
if (V.isStruct() || V.isUnion()) {
// Dependent types are not supposed to be described as
// TemplateParamObjectDecls.
if (T->isDependentType() || T->isInstantiationDependentType())
return nullptr;
[c++20] P1907R1: Support for generalized non-type template arguments of scalar type. (#78041) Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and reverted because a dependency commit was reverted, then committed again as 4b574008aef5a7235c1f894ab065fe300d26e786 and reverted again because "dependency commit" 5a391d38ac6c561ba908334d427f26124ed9132e was reverted. But it doesn't seem that 5a391d38ac6c was a real dependency for this. This commit incorporates 4b574008aef5a7235c1f894ab065fe300d26e786 and 18e093faf726d15f210ab4917142beec51848258 by Richard Smith (@zygoloid), with some minor fixes, most notably: - `UncommonValue` renamed to `StructuralValue` - `VK_PRValue` instead of `VK_RValue` as default kind in lvalue and member pointer handling branch in `BuildExpressionFromNonTypeTemplateArgumentValue`; - handling of `StructuralValue` in `IsTypeDeclaredInsideVisitor`; - filling in `SugaredConverted` along with `CanonicalConverted` parameter in `Sema::CheckTemplateArgument`; - minor cleanup in `TemplateInstantiator::transformNonTypeTemplateParmRef`; - `TemplateArgument` constructors refactored; - `ODRHash` calculation for `UncommonValue`; - USR generation for `UncommonValue`; - more correct MS compatibility mangling algorithm (tested on MSVC ver. 19.35; toolset ver. 143); - IR emitting fixed on using a subobject as a template argument when the corresponding template parameter is used in an lvalue context; - `noundef` attribute and opaque pointers in `template-arguments` test; - analysis for C++17 mode is turned off for templates in `warn-bool-conversion` test; in C++17 and C++20 mode, array reference used as a template argument of pointer type produces template argument of UncommonValue type, and `BuildExpressionFromNonTypeTemplateArgumentValue` makes `OpaqueValueExpr` for it, and `DiagnoseAlwaysNonNullPointer` cannot see through it; despite of "These cases should not warn" comment, I'm not sure about correct behavior; I'd expect a suggestion to replace `if` by `if constexpr`; - `temp.arg.nontype/p1.cpp` and `dr18xx.cpp` tests fixed.
2024-01-21 23:28:57 +03:00
return Ctx.getTemplateParamObjectDecl(T, V);
}
[c++20] P1907R1: Support for generalized non-type template arguments of scalar type. (#78041) Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and reverted because a dependency commit was reverted, then committed again as 4b574008aef5a7235c1f894ab065fe300d26e786 and reverted again because "dependency commit" 5a391d38ac6c561ba908334d427f26124ed9132e was reverted. But it doesn't seem that 5a391d38ac6c was a real dependency for this. This commit incorporates 4b574008aef5a7235c1f894ab065fe300d26e786 and 18e093faf726d15f210ab4917142beec51848258 by Richard Smith (@zygoloid), with some minor fixes, most notably: - `UncommonValue` renamed to `StructuralValue` - `VK_PRValue` instead of `VK_RValue` as default kind in lvalue and member pointer handling branch in `BuildExpressionFromNonTypeTemplateArgumentValue`; - handling of `StructuralValue` in `IsTypeDeclaredInsideVisitor`; - filling in `SugaredConverted` along with `CanonicalConverted` parameter in `Sema::CheckTemplateArgument`; - minor cleanup in `TemplateInstantiator::transformNonTypeTemplateParmRef`; - `TemplateArgument` constructors refactored; - `ODRHash` calculation for `UncommonValue`; - USR generation for `UncommonValue`; - more correct MS compatibility mangling algorithm (tested on MSVC ver. 19.35; toolset ver. 143); - IR emitting fixed on using a subobject as a template argument when the corresponding template parameter is used in an lvalue context; - `noundef` attribute and opaque pointers in `template-arguments` test; - analysis for C++17 mode is turned off for templates in `warn-bool-conversion` test; in C++17 and C++20 mode, array reference used as a template argument of pointer type produces template argument of UncommonValue type, and `BuildExpressionFromNonTypeTemplateArgumentValue` makes `OpaqueValueExpr` for it, and `DiagnoseAlwaysNonNullPointer` cannot see through it; despite of "These cases should not warn" comment, I'm not sure about correct behavior; I'd expect a suggestion to replace `if` by `if constexpr`; - `temp.arg.nontype/p1.cpp` and `dr18xx.cpp` tests fixed.
2024-01-21 23:28:57 +03:00
// Pointers and references with an empty path use the special 'Declaration'
// representation.
if (V.isLValue() && V.hasLValuePath() && V.getLValuePath().empty() &&
!V.isLValueOnePastTheEnd())
return V.getLValueBase().dyn_cast<const ValueDecl *>();
// Everything else uses the 'structural' representation.
return nullptr;
}
TemplateArgument::TemplateArgument(const ASTContext &Ctx, QualType Type,
const APValue &V, bool IsDefaulted) {
if (Type->isIntegralOrEnumerationType() && V.isInt())
initFromIntegral(Ctx, V.getInt(), Type, IsDefaulted);
else if ((V.isLValue() && V.isNullPointer()) ||
(V.isMemberPointer() && !V.getMemberPointerDecl()))
initFromType(Type, /*isNullPtr=*/true, IsDefaulted);
else if (const ValueDecl *VD = getAsSimpleValueDeclRef(Ctx, Type, V))
// FIXME: The Declaration form should expose a const ValueDecl*.
initFromDeclaration(const_cast<ValueDecl *>(VD), Type, IsDefaulted);
else
initFromStructural(Ctx, Type, V, IsDefaulted);
}
TemplateArgument
TemplateArgument::CreatePackCopy(ASTContext &Context,
ArrayRef<TemplateArgument> Args) {
if (Args.empty())
return getEmptyPack();
return TemplateArgument(Args.copy(Context));
}
TemplateArgumentDependence TemplateArgument::getDependence() const {
auto Deps = TemplateArgumentDependence::None;
switch (getKind()) {
case Null:
llvm_unreachable("Should not have a NULL template argument");
case Type:
Deps = toTemplateArgumentDependence(getAsType()->getDependence());
if (isa<PackExpansionType>(getAsType()))
Deps |= TemplateArgumentDependence::Dependent;
return Deps;
case Template:
return toTemplateArgumentDependence(getAsTemplate().getDependence());
case TemplateExpansion:
return TemplateArgumentDependence::Dependent |
TemplateArgumentDependence::Instantiation;
Revert "Following up on PR48517, fix handling of template arguments that refer" Combined with 'da98651 - Revert "DR2064: decltype(E) is only a dependent', this change (5a391d3) caused verifier errors when building Chromium. See https://crbug.com/1168494#c1 for a reproducer. Additionally it reverts changes that were dependent on this one, see below. > Following up on PR48517, fix handling of template arguments that refer > to dependent declarations. > > Treat an id-expression that names a local variable in a templated > function as being instantiation-dependent. > > This addresses a language defect whereby a reference to a dependent > declaration can be formed without any construct being value-dependent. > Fixing that through value-dependence turns out to be problematic, so > instead this patch takes the approach (proposed on the core reflector) > of allowing the use of pointers or references to (but not values of) > dependent declarations inside value-dependent expressions, and instead > treating template arguments as dependent if they evaluate to a constant > involving such dependent declarations. > > This ends up affecting a bunch of OpenMP tests, due to OpenMP > imprecisely handling instantiation-dependent constructs, bailing out > early instead of processing dependent constructs to the extent possible > when handling the template. > > Previously committed as 8c1f2d15b826591cdf6bd6b468b8a7d23377b29e, and > reverted because a dependency commit was reverted. This reverts commit 5a391d38ac6c561ba908334d427f26124ed9132e. It also restores clang/test/SemaCXX/coroutines.cpp to its state before da986511fb9da1a46a0ca4dba2e49e2426036303. Revert "[c++20] P1907R1: Support for generalized non-type template arguments of scalar type." > Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and > reverted because a dependency commit was reverted. This incorporates the > following follow-on commits that were also reverted: > > 7e84aa1b81e72d44bcc58ffe1731bfc7abb73ce0 by Simon Pilgrim > ed13d8c66781b50ff007cb089c5905f9bb9e8af2 by me > 95c7b6cadbc9a3d4376ef44edbeb3c8bb5b8d7fc by Sam McCall > 430d5d8429473c2b10b109991d7577a3cea41140 by Dave Zarzycki This reverts commit 4b574008aef5a7235c1f894ab065fe300d26e786. Revert "[msabi] Mangle a template argument referring to array-to-pointer decay" > [msabi] Mangle a template argument referring to array-to-pointer decay > applied to an array the same as the array itself. > > This follows MS ABI, and corrects a regression from the implementation > of generalized non-type template parameters, where we "forgot" how to > mangle this case. This reverts commit 18e093faf726d15f210ab4917142beec51848258.
2021-01-20 15:25:33 +01:00
case Declaration: {
auto *DC = dyn_cast<DeclContext>(getAsDecl());
if (!DC)
DC = getAsDecl()->getDeclContext();
if (DC->isDependentContext())
Deps = TemplateArgumentDependence::Dependent |
TemplateArgumentDependence::Instantiation;
return Deps;
}
case NullPtr:
case Integral:
[c++20] P1907R1: Support for generalized non-type template arguments of scalar type. (#78041) Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and reverted because a dependency commit was reverted, then committed again as 4b574008aef5a7235c1f894ab065fe300d26e786 and reverted again because "dependency commit" 5a391d38ac6c561ba908334d427f26124ed9132e was reverted. But it doesn't seem that 5a391d38ac6c was a real dependency for this. This commit incorporates 4b574008aef5a7235c1f894ab065fe300d26e786 and 18e093faf726d15f210ab4917142beec51848258 by Richard Smith (@zygoloid), with some minor fixes, most notably: - `UncommonValue` renamed to `StructuralValue` - `VK_PRValue` instead of `VK_RValue` as default kind in lvalue and member pointer handling branch in `BuildExpressionFromNonTypeTemplateArgumentValue`; - handling of `StructuralValue` in `IsTypeDeclaredInsideVisitor`; - filling in `SugaredConverted` along with `CanonicalConverted` parameter in `Sema::CheckTemplateArgument`; - minor cleanup in `TemplateInstantiator::transformNonTypeTemplateParmRef`; - `TemplateArgument` constructors refactored; - `ODRHash` calculation for `UncommonValue`; - USR generation for `UncommonValue`; - more correct MS compatibility mangling algorithm (tested on MSVC ver. 19.35; toolset ver. 143); - IR emitting fixed on using a subobject as a template argument when the corresponding template parameter is used in an lvalue context; - `noundef` attribute and opaque pointers in `template-arguments` test; - analysis for C++17 mode is turned off for templates in `warn-bool-conversion` test; in C++17 and C++20 mode, array reference used as a template argument of pointer type produces template argument of UncommonValue type, and `BuildExpressionFromNonTypeTemplateArgumentValue` makes `OpaqueValueExpr` for it, and `DiagnoseAlwaysNonNullPointer` cannot see through it; despite of "These cases should not warn" comment, I'm not sure about correct behavior; I'd expect a suggestion to replace `if` by `if constexpr`; - `temp.arg.nontype/p1.cpp` and `dr18xx.cpp` tests fixed.
2024-01-21 23:28:57 +03:00
case StructuralValue:
return TemplateArgumentDependence::None;
case Expression:
Deps = toTemplateArgumentDependence(getAsExpr()->getDependence());
Revert "Following up on PR48517, fix handling of template arguments that refer" Combined with 'da98651 - Revert "DR2064: decltype(E) is only a dependent', this change (5a391d3) caused verifier errors when building Chromium. See https://crbug.com/1168494#c1 for a reproducer. Additionally it reverts changes that were dependent on this one, see below. > Following up on PR48517, fix handling of template arguments that refer > to dependent declarations. > > Treat an id-expression that names a local variable in a templated > function as being instantiation-dependent. > > This addresses a language defect whereby a reference to a dependent > declaration can be formed without any construct being value-dependent. > Fixing that through value-dependence turns out to be problematic, so > instead this patch takes the approach (proposed on the core reflector) > of allowing the use of pointers or references to (but not values of) > dependent declarations inside value-dependent expressions, and instead > treating template arguments as dependent if they evaluate to a constant > involving such dependent declarations. > > This ends up affecting a bunch of OpenMP tests, due to OpenMP > imprecisely handling instantiation-dependent constructs, bailing out > early instead of processing dependent constructs to the extent possible > when handling the template. > > Previously committed as 8c1f2d15b826591cdf6bd6b468b8a7d23377b29e, and > reverted because a dependency commit was reverted. This reverts commit 5a391d38ac6c561ba908334d427f26124ed9132e. It also restores clang/test/SemaCXX/coroutines.cpp to its state before da986511fb9da1a46a0ca4dba2e49e2426036303. Revert "[c++20] P1907R1: Support for generalized non-type template arguments of scalar type." > Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and > reverted because a dependency commit was reverted. This incorporates the > following follow-on commits that were also reverted: > > 7e84aa1b81e72d44bcc58ffe1731bfc7abb73ce0 by Simon Pilgrim > ed13d8c66781b50ff007cb089c5905f9bb9e8af2 by me > 95c7b6cadbc9a3d4376ef44edbeb3c8bb5b8d7fc by Sam McCall > 430d5d8429473c2b10b109991d7577a3cea41140 by Dave Zarzycki This reverts commit 4b574008aef5a7235c1f894ab065fe300d26e786. Revert "[msabi] Mangle a template argument referring to array-to-pointer decay" > [msabi] Mangle a template argument referring to array-to-pointer decay > applied to an array the same as the array itself. > > This follows MS ABI, and corrects a regression from the implementation > of generalized non-type template parameters, where we "forgot" how to > mangle this case. This reverts commit 18e093faf726d15f210ab4917142beec51848258.
2021-01-20 15:25:33 +01:00
if (isa<PackExpansionExpr>(getAsExpr()))
Deps |= TemplateArgumentDependence::Dependent |
TemplateArgumentDependence::Instantiation;
return Deps;
case Pack:
for (const auto &P : pack_elements())
Deps |= P.getDependence();
return Deps;
}
llvm_unreachable("unhandled ArgKind");
}
bool TemplateArgument::isDependent() const {
return getDependence() & TemplateArgumentDependence::Dependent;
}
bool TemplateArgument::isInstantiationDependent() const {
return getDependence() & TemplateArgumentDependence::Instantiation;
}
bool TemplateArgument::isPackExpansion() const {
switch (getKind()) {
case Null:
case Declaration:
case Integral:
[c++20] P1907R1: Support for generalized non-type template arguments of scalar type. (#78041) Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and reverted because a dependency commit was reverted, then committed again as 4b574008aef5a7235c1f894ab065fe300d26e786 and reverted again because "dependency commit" 5a391d38ac6c561ba908334d427f26124ed9132e was reverted. But it doesn't seem that 5a391d38ac6c was a real dependency for this. This commit incorporates 4b574008aef5a7235c1f894ab065fe300d26e786 and 18e093faf726d15f210ab4917142beec51848258 by Richard Smith (@zygoloid), with some minor fixes, most notably: - `UncommonValue` renamed to `StructuralValue` - `VK_PRValue` instead of `VK_RValue` as default kind in lvalue and member pointer handling branch in `BuildExpressionFromNonTypeTemplateArgumentValue`; - handling of `StructuralValue` in `IsTypeDeclaredInsideVisitor`; - filling in `SugaredConverted` along with `CanonicalConverted` parameter in `Sema::CheckTemplateArgument`; - minor cleanup in `TemplateInstantiator::transformNonTypeTemplateParmRef`; - `TemplateArgument` constructors refactored; - `ODRHash` calculation for `UncommonValue`; - USR generation for `UncommonValue`; - more correct MS compatibility mangling algorithm (tested on MSVC ver. 19.35; toolset ver. 143); - IR emitting fixed on using a subobject as a template argument when the corresponding template parameter is used in an lvalue context; - `noundef` attribute and opaque pointers in `template-arguments` test; - analysis for C++17 mode is turned off for templates in `warn-bool-conversion` test; in C++17 and C++20 mode, array reference used as a template argument of pointer type produces template argument of UncommonValue type, and `BuildExpressionFromNonTypeTemplateArgumentValue` makes `OpaqueValueExpr` for it, and `DiagnoseAlwaysNonNullPointer` cannot see through it; despite of "These cases should not warn" comment, I'm not sure about correct behavior; I'd expect a suggestion to replace `if` by `if constexpr`; - `temp.arg.nontype/p1.cpp` and `dr18xx.cpp` tests fixed.
2024-01-21 23:28:57 +03:00
case StructuralValue:
case Pack:
case Template:
case NullPtr:
return false;
case TemplateExpansion:
return true;
case Type:
return isa<PackExpansionType>(getAsType());
case Expression:
return isa<PackExpansionExpr>(getAsExpr());
}
llvm_unreachable("Invalid TemplateArgument Kind!");
}
bool TemplateArgument::containsUnexpandedParameterPack() const {
return getDependence() & TemplateArgumentDependence::UnexpandedPack;
}
UnsignedOrNone TemplateArgument::getNumTemplateExpansions() const {
assert(getKind() == TemplateExpansion);
return TemplateArg.NumExpansions;
}
QualType TemplateArgument::getNonTypeTemplateArgumentType() const {
switch (getKind()) {
case TemplateArgument::Null:
case TemplateArgument::Type:
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
case TemplateArgument::Pack:
return QualType();
case TemplateArgument::Integral:
return getIntegralType();
case TemplateArgument::Expression:
return getAsExpr()->getType();
case TemplateArgument::Declaration:
return getParamTypeForDecl();
case TemplateArgument::NullPtr:
return getNullPtrType();
[c++20] P1907R1: Support for generalized non-type template arguments of scalar type. (#78041) Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and reverted because a dependency commit was reverted, then committed again as 4b574008aef5a7235c1f894ab065fe300d26e786 and reverted again because "dependency commit" 5a391d38ac6c561ba908334d427f26124ed9132e was reverted. But it doesn't seem that 5a391d38ac6c was a real dependency for this. This commit incorporates 4b574008aef5a7235c1f894ab065fe300d26e786 and 18e093faf726d15f210ab4917142beec51848258 by Richard Smith (@zygoloid), with some minor fixes, most notably: - `UncommonValue` renamed to `StructuralValue` - `VK_PRValue` instead of `VK_RValue` as default kind in lvalue and member pointer handling branch in `BuildExpressionFromNonTypeTemplateArgumentValue`; - handling of `StructuralValue` in `IsTypeDeclaredInsideVisitor`; - filling in `SugaredConverted` along with `CanonicalConverted` parameter in `Sema::CheckTemplateArgument`; - minor cleanup in `TemplateInstantiator::transformNonTypeTemplateParmRef`; - `TemplateArgument` constructors refactored; - `ODRHash` calculation for `UncommonValue`; - USR generation for `UncommonValue`; - more correct MS compatibility mangling algorithm (tested on MSVC ver. 19.35; toolset ver. 143); - IR emitting fixed on using a subobject as a template argument when the corresponding template parameter is used in an lvalue context; - `noundef` attribute and opaque pointers in `template-arguments` test; - analysis for C++17 mode is turned off for templates in `warn-bool-conversion` test; in C++17 and C++20 mode, array reference used as a template argument of pointer type produces template argument of UncommonValue type, and `BuildExpressionFromNonTypeTemplateArgumentValue` makes `OpaqueValueExpr` for it, and `DiagnoseAlwaysNonNullPointer` cannot see through it; despite of "These cases should not warn" comment, I'm not sure about correct behavior; I'd expect a suggestion to replace `if` by `if constexpr`; - `temp.arg.nontype/p1.cpp` and `dr18xx.cpp` tests fixed.
2024-01-21 23:28:57 +03:00
case TemplateArgument::StructuralValue:
return getStructuralValueType();
}
llvm_unreachable("Invalid TemplateArgument Kind!");
}
void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &Context) const {
ID.AddInteger(getKind());
switch (getKind()) {
case Null:
break;
case Type:
getAsType().Profile(ID);
break;
case NullPtr:
getNullPtrType().Profile(ID);
break;
case Declaration:
getParamTypeForDecl().Profile(ID);
ID.AddPointer(getAsDecl());
break;
case TemplateExpansion:
ID.AddInteger(TemplateArg.NumExpansions.toInternalRepresentation());
[[fallthrough]];
case Template:
ID.AddPointer(TemplateArg.Name);
break;
case Integral:
Revert "Following up on PR48517, fix handling of template arguments that refer" Combined with 'da98651 - Revert "DR2064: decltype(E) is only a dependent', this change (5a391d3) caused verifier errors when building Chromium. See https://crbug.com/1168494#c1 for a reproducer. Additionally it reverts changes that were dependent on this one, see below. > Following up on PR48517, fix handling of template arguments that refer > to dependent declarations. > > Treat an id-expression that names a local variable in a templated > function as being instantiation-dependent. > > This addresses a language defect whereby a reference to a dependent > declaration can be formed without any construct being value-dependent. > Fixing that through value-dependence turns out to be problematic, so > instead this patch takes the approach (proposed on the core reflector) > of allowing the use of pointers or references to (but not values of) > dependent declarations inside value-dependent expressions, and instead > treating template arguments as dependent if they evaluate to a constant > involving such dependent declarations. > > This ends up affecting a bunch of OpenMP tests, due to OpenMP > imprecisely handling instantiation-dependent constructs, bailing out > early instead of processing dependent constructs to the extent possible > when handling the template. > > Previously committed as 8c1f2d15b826591cdf6bd6b468b8a7d23377b29e, and > reverted because a dependency commit was reverted. This reverts commit 5a391d38ac6c561ba908334d427f26124ed9132e. It also restores clang/test/SemaCXX/coroutines.cpp to its state before da986511fb9da1a46a0ca4dba2e49e2426036303. Revert "[c++20] P1907R1: Support for generalized non-type template arguments of scalar type." > Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and > reverted because a dependency commit was reverted. This incorporates the > following follow-on commits that were also reverted: > > 7e84aa1b81e72d44bcc58ffe1731bfc7abb73ce0 by Simon Pilgrim > ed13d8c66781b50ff007cb089c5905f9bb9e8af2 by me > 95c7b6cadbc9a3d4376ef44edbeb3c8bb5b8d7fc by Sam McCall > 430d5d8429473c2b10b109991d7577a3cea41140 by Dave Zarzycki This reverts commit 4b574008aef5a7235c1f894ab065fe300d26e786. Revert "[msabi] Mangle a template argument referring to array-to-pointer decay" > [msabi] Mangle a template argument referring to array-to-pointer decay > applied to an array the same as the array itself. > > This follows MS ABI, and corrects a regression from the implementation > of generalized non-type template parameters, where we "forgot" how to > mangle this case. This reverts commit 18e093faf726d15f210ab4917142beec51848258.
2021-01-20 15:25:33 +01:00
getIntegralType().Profile(ID);
[c++20] P1907R1: Support for generalized non-type template arguments of scalar type. (#78041) Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and reverted because a dependency commit was reverted, then committed again as 4b574008aef5a7235c1f894ab065fe300d26e786 and reverted again because "dependency commit" 5a391d38ac6c561ba908334d427f26124ed9132e was reverted. But it doesn't seem that 5a391d38ac6c was a real dependency for this. This commit incorporates 4b574008aef5a7235c1f894ab065fe300d26e786 and 18e093faf726d15f210ab4917142beec51848258 by Richard Smith (@zygoloid), with some minor fixes, most notably: - `UncommonValue` renamed to `StructuralValue` - `VK_PRValue` instead of `VK_RValue` as default kind in lvalue and member pointer handling branch in `BuildExpressionFromNonTypeTemplateArgumentValue`; - handling of `StructuralValue` in `IsTypeDeclaredInsideVisitor`; - filling in `SugaredConverted` along with `CanonicalConverted` parameter in `Sema::CheckTemplateArgument`; - minor cleanup in `TemplateInstantiator::transformNonTypeTemplateParmRef`; - `TemplateArgument` constructors refactored; - `ODRHash` calculation for `UncommonValue`; - USR generation for `UncommonValue`; - more correct MS compatibility mangling algorithm (tested on MSVC ver. 19.35; toolset ver. 143); - IR emitting fixed on using a subobject as a template argument when the corresponding template parameter is used in an lvalue context; - `noundef` attribute and opaque pointers in `template-arguments` test; - analysis for C++17 mode is turned off for templates in `warn-bool-conversion` test; in C++17 and C++20 mode, array reference used as a template argument of pointer type produces template argument of UncommonValue type, and `BuildExpressionFromNonTypeTemplateArgumentValue` makes `OpaqueValueExpr` for it, and `DiagnoseAlwaysNonNullPointer` cannot see through it; despite of "These cases should not warn" comment, I'm not sure about correct behavior; I'd expect a suggestion to replace `if` by `if constexpr`; - `temp.arg.nontype/p1.cpp` and `dr18xx.cpp` tests fixed.
2024-01-21 23:28:57 +03:00
getAsIntegral().Profile(ID);
break;
case StructuralValue:
getStructuralValueType().Profile(ID);
getAsStructuralValue().Profile(ID);
break;
case Expression: {
const Expr *E = getAsExpr();
bool IsCanonical = isCanonicalExpr();
ID.AddBoolean(IsCanonical);
if (IsCanonical)
E->Profile(ID, Context, true);
else
ID.AddPointer(E);
break;
}
case Pack:
ID.AddInteger(Args.NumArgs);
for (unsigned I = 0; I != Args.NumArgs; ++I)
Args.Args[I].Profile(ID, Context);
}
}
bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
if (getKind() != Other.getKind()) return false;
switch (getKind()) {
case Null:
case Type:
case NullPtr:
return TypeOrValue.V == Other.TypeOrValue.V;
case Expression:
return TypeOrValue.V == Other.TypeOrValue.V &&
TypeOrValue.IsCanonicalExpr == Other.TypeOrValue.IsCanonicalExpr;
case Template:
case TemplateExpansion:
return TemplateArg.Name == Other.TemplateArg.Name &&
TemplateArg.NumExpansions == Other.TemplateArg.NumExpansions;
case Declaration:
return getAsDecl() == Other.getAsDecl() &&
getParamTypeForDecl() == Other.getParamTypeForDecl();
case Integral:
return getIntegralType() == Other.getIntegralType() &&
getAsIntegral() == Other.getAsIntegral();
[c++20] P1907R1: Support for generalized non-type template arguments of scalar type. (#78041) Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and reverted because a dependency commit was reverted, then committed again as 4b574008aef5a7235c1f894ab065fe300d26e786 and reverted again because "dependency commit" 5a391d38ac6c561ba908334d427f26124ed9132e was reverted. But it doesn't seem that 5a391d38ac6c was a real dependency for this. This commit incorporates 4b574008aef5a7235c1f894ab065fe300d26e786 and 18e093faf726d15f210ab4917142beec51848258 by Richard Smith (@zygoloid), with some minor fixes, most notably: - `UncommonValue` renamed to `StructuralValue` - `VK_PRValue` instead of `VK_RValue` as default kind in lvalue and member pointer handling branch in `BuildExpressionFromNonTypeTemplateArgumentValue`; - handling of `StructuralValue` in `IsTypeDeclaredInsideVisitor`; - filling in `SugaredConverted` along with `CanonicalConverted` parameter in `Sema::CheckTemplateArgument`; - minor cleanup in `TemplateInstantiator::transformNonTypeTemplateParmRef`; - `TemplateArgument` constructors refactored; - `ODRHash` calculation for `UncommonValue`; - USR generation for `UncommonValue`; - more correct MS compatibility mangling algorithm (tested on MSVC ver. 19.35; toolset ver. 143); - IR emitting fixed on using a subobject as a template argument when the corresponding template parameter is used in an lvalue context; - `noundef` attribute and opaque pointers in `template-arguments` test; - analysis for C++17 mode is turned off for templates in `warn-bool-conversion` test; in C++17 and C++20 mode, array reference used as a template argument of pointer type produces template argument of UncommonValue type, and `BuildExpressionFromNonTypeTemplateArgumentValue` makes `OpaqueValueExpr` for it, and `DiagnoseAlwaysNonNullPointer` cannot see through it; despite of "These cases should not warn" comment, I'm not sure about correct behavior; I'd expect a suggestion to replace `if` by `if constexpr`; - `temp.arg.nontype/p1.cpp` and `dr18xx.cpp` tests fixed.
2024-01-21 23:28:57 +03:00
case StructuralValue: {
if (getStructuralValueType().getCanonicalType() !=
Other.getStructuralValueType().getCanonicalType())
[c++20] P1907R1: Support for generalized non-type template arguments of scalar type. (#78041) Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and reverted because a dependency commit was reverted, then committed again as 4b574008aef5a7235c1f894ab065fe300d26e786 and reverted again because "dependency commit" 5a391d38ac6c561ba908334d427f26124ed9132e was reverted. But it doesn't seem that 5a391d38ac6c was a real dependency for this. This commit incorporates 4b574008aef5a7235c1f894ab065fe300d26e786 and 18e093faf726d15f210ab4917142beec51848258 by Richard Smith (@zygoloid), with some minor fixes, most notably: - `UncommonValue` renamed to `StructuralValue` - `VK_PRValue` instead of `VK_RValue` as default kind in lvalue and member pointer handling branch in `BuildExpressionFromNonTypeTemplateArgumentValue`; - handling of `StructuralValue` in `IsTypeDeclaredInsideVisitor`; - filling in `SugaredConverted` along with `CanonicalConverted` parameter in `Sema::CheckTemplateArgument`; - minor cleanup in `TemplateInstantiator::transformNonTypeTemplateParmRef`; - `TemplateArgument` constructors refactored; - `ODRHash` calculation for `UncommonValue`; - USR generation for `UncommonValue`; - more correct MS compatibility mangling algorithm (tested on MSVC ver. 19.35; toolset ver. 143); - IR emitting fixed on using a subobject as a template argument when the corresponding template parameter is used in an lvalue context; - `noundef` attribute and opaque pointers in `template-arguments` test; - analysis for C++17 mode is turned off for templates in `warn-bool-conversion` test; in C++17 and C++20 mode, array reference used as a template argument of pointer type produces template argument of UncommonValue type, and `BuildExpressionFromNonTypeTemplateArgumentValue` makes `OpaqueValueExpr` for it, and `DiagnoseAlwaysNonNullPointer` cannot see through it; despite of "These cases should not warn" comment, I'm not sure about correct behavior; I'd expect a suggestion to replace `if` by `if constexpr`; - `temp.arg.nontype/p1.cpp` and `dr18xx.cpp` tests fixed.
2024-01-21 23:28:57 +03:00
return false;
llvm::FoldingSetNodeID A, B;
getAsStructuralValue().Profile(A);
Other.getAsStructuralValue().Profile(B);
return A == B;
}
case Pack:
if (Args.NumArgs != Other.Args.NumArgs) return false;
for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
return false;
return true;
}
llvm_unreachable("Invalid TemplateArgument Kind!");
}
TemplateArgument TemplateArgument::getPackExpansionPattern() const {
assert(isPackExpansion());
switch (getKind()) {
case Type:
return getAsType()->castAs<PackExpansionType>()->getPattern();
case Expression:
return TemplateArgument(cast<PackExpansionExpr>(getAsExpr())->getPattern(),
isCanonicalExpr());
case TemplateExpansion:
return TemplateArgument(getAsTemplateOrTemplatePattern());
case Declaration:
case Integral:
[c++20] P1907R1: Support for generalized non-type template arguments of scalar type. (#78041) Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and reverted because a dependency commit was reverted, then committed again as 4b574008aef5a7235c1f894ab065fe300d26e786 and reverted again because "dependency commit" 5a391d38ac6c561ba908334d427f26124ed9132e was reverted. But it doesn't seem that 5a391d38ac6c was a real dependency for this. This commit incorporates 4b574008aef5a7235c1f894ab065fe300d26e786 and 18e093faf726d15f210ab4917142beec51848258 by Richard Smith (@zygoloid), with some minor fixes, most notably: - `UncommonValue` renamed to `StructuralValue` - `VK_PRValue` instead of `VK_RValue` as default kind in lvalue and member pointer handling branch in `BuildExpressionFromNonTypeTemplateArgumentValue`; - handling of `StructuralValue` in `IsTypeDeclaredInsideVisitor`; - filling in `SugaredConverted` along with `CanonicalConverted` parameter in `Sema::CheckTemplateArgument`; - minor cleanup in `TemplateInstantiator::transformNonTypeTemplateParmRef`; - `TemplateArgument` constructors refactored; - `ODRHash` calculation for `UncommonValue`; - USR generation for `UncommonValue`; - more correct MS compatibility mangling algorithm (tested on MSVC ver. 19.35; toolset ver. 143); - IR emitting fixed on using a subobject as a template argument when the corresponding template parameter is used in an lvalue context; - `noundef` attribute and opaque pointers in `template-arguments` test; - analysis for C++17 mode is turned off for templates in `warn-bool-conversion` test; in C++17 and C++20 mode, array reference used as a template argument of pointer type produces template argument of UncommonValue type, and `BuildExpressionFromNonTypeTemplateArgumentValue` makes `OpaqueValueExpr` for it, and `DiagnoseAlwaysNonNullPointer` cannot see through it; despite of "These cases should not warn" comment, I'm not sure about correct behavior; I'd expect a suggestion to replace `if` by `if constexpr`; - `temp.arg.nontype/p1.cpp` and `dr18xx.cpp` tests fixed.
2024-01-21 23:28:57 +03:00
case StructuralValue:
case Pack:
case Null:
case Template:
case NullPtr:
return TemplateArgument();
}
llvm_unreachable("Invalid TemplateArgument Kind!");
}
void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out,
bool IncludeType) const {
switch (getKind()) {
case Null:
Out << "(no value)";
break;
case Type: {
PrintingPolicy SubPolicy(Policy);
SubPolicy.SuppressStrongLifetime = true;
getAsType().print(Out, SubPolicy);
break;
}
case Declaration: {
2025-01-27 00:25:19 -03:00
ValueDecl *VD = getAsDecl();
if (getParamTypeForDecl()->isRecordType()) {
2025-01-27 00:25:19 -03:00
if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(VD)) {
TPO->getType().getUnqualifiedType().print(Out, Policy);
TPO->printAsInit(Out, Policy);
break;
}
}
2025-01-27 00:25:19 -03:00
if (needsAmpersandOnTemplateArg(getParamTypeForDecl(), VD->getType()))
Out << "&";
VD->printQualifiedName(Out);
break;
}
[c++20] P1907R1: Support for generalized non-type template arguments of scalar type. (#78041) Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and reverted because a dependency commit was reverted, then committed again as 4b574008aef5a7235c1f894ab065fe300d26e786 and reverted again because "dependency commit" 5a391d38ac6c561ba908334d427f26124ed9132e was reverted. But it doesn't seem that 5a391d38ac6c was a real dependency for this. This commit incorporates 4b574008aef5a7235c1f894ab065fe300d26e786 and 18e093faf726d15f210ab4917142beec51848258 by Richard Smith (@zygoloid), with some minor fixes, most notably: - `UncommonValue` renamed to `StructuralValue` - `VK_PRValue` instead of `VK_RValue` as default kind in lvalue and member pointer handling branch in `BuildExpressionFromNonTypeTemplateArgumentValue`; - handling of `StructuralValue` in `IsTypeDeclaredInsideVisitor`; - filling in `SugaredConverted` along with `CanonicalConverted` parameter in `Sema::CheckTemplateArgument`; - minor cleanup in `TemplateInstantiator::transformNonTypeTemplateParmRef`; - `TemplateArgument` constructors refactored; - `ODRHash` calculation for `UncommonValue`; - USR generation for `UncommonValue`; - more correct MS compatibility mangling algorithm (tested on MSVC ver. 19.35; toolset ver. 143); - IR emitting fixed on using a subobject as a template argument when the corresponding template parameter is used in an lvalue context; - `noundef` attribute and opaque pointers in `template-arguments` test; - analysis for C++17 mode is turned off for templates in `warn-bool-conversion` test; in C++17 and C++20 mode, array reference used as a template argument of pointer type produces template argument of UncommonValue type, and `BuildExpressionFromNonTypeTemplateArgumentValue` makes `OpaqueValueExpr` for it, and `DiagnoseAlwaysNonNullPointer` cannot see through it; despite of "These cases should not warn" comment, I'm not sure about correct behavior; I'd expect a suggestion to replace `if` by `if constexpr`; - `temp.arg.nontype/p1.cpp` and `dr18xx.cpp` tests fixed.
2024-01-21 23:28:57 +03:00
case StructuralValue:
getAsStructuralValue().printPretty(Out, Policy, getStructuralValueType());
break;
case NullPtr:
// FIXME: Include the type if it's not obvious from the context.
Out << "nullptr";
break;
case Template: {
getAsTemplate().print(Out, Policy);
break;
}
case TemplateExpansion:
getAsTemplateOrTemplatePattern().print(Out, Policy);
Out << "...";
break;
case Integral:
printIntegral(*this, Out, Policy, IncludeType);
break;
case Expression: {
PrintingPolicy ExprPolicy = Policy;
ExprPolicy.PrintAsCanonical = isCanonicalExpr();
getAsExpr()->printPretty(Out, nullptr, ExprPolicy);
break;
}
case Pack:
Out << "<";
bool First = true;
for (const auto &P : pack_elements()) {
if (First)
First = false;
else
Out << ", ";
P.print(Policy, Out, IncludeType);
}
Out << ">";
break;
}
}
//===----------------------------------------------------------------------===//
// TemplateArgumentLoc Implementation
//===----------------------------------------------------------------------===//
SourceRange TemplateArgumentLoc::getSourceRange() const {
switch (Argument.getKind()) {
case TemplateArgument::Expression:
return getSourceExpression()->getSourceRange();
case TemplateArgument::Declaration:
return getSourceDeclExpression()->getSourceRange();
case TemplateArgument::NullPtr:
return getSourceNullPtrExpression()->getSourceRange();
case TemplateArgument::Type:
if (TypeSourceInfo *TSI = getTypeSourceInfo())
return TSI->getTypeLoc().getSourceRange();
else
return SourceRange();
case TemplateArgument::Template:
if (getTemplateQualifierLoc())
return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
getTemplateNameLoc());
return SourceRange(getTemplateNameLoc());
case TemplateArgument::TemplateExpansion:
if (getTemplateQualifierLoc())
return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
getTemplateEllipsisLoc());
return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
case TemplateArgument::Integral:
return getSourceIntegralExpression()->getSourceRange();
[c++20] P1907R1: Support for generalized non-type template arguments of scalar type. (#78041) Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and reverted because a dependency commit was reverted, then committed again as 4b574008aef5a7235c1f894ab065fe300d26e786 and reverted again because "dependency commit" 5a391d38ac6c561ba908334d427f26124ed9132e was reverted. But it doesn't seem that 5a391d38ac6c was a real dependency for this. This commit incorporates 4b574008aef5a7235c1f894ab065fe300d26e786 and 18e093faf726d15f210ab4917142beec51848258 by Richard Smith (@zygoloid), with some minor fixes, most notably: - `UncommonValue` renamed to `StructuralValue` - `VK_PRValue` instead of `VK_RValue` as default kind in lvalue and member pointer handling branch in `BuildExpressionFromNonTypeTemplateArgumentValue`; - handling of `StructuralValue` in `IsTypeDeclaredInsideVisitor`; - filling in `SugaredConverted` along with `CanonicalConverted` parameter in `Sema::CheckTemplateArgument`; - minor cleanup in `TemplateInstantiator::transformNonTypeTemplateParmRef`; - `TemplateArgument` constructors refactored; - `ODRHash` calculation for `UncommonValue`; - USR generation for `UncommonValue`; - more correct MS compatibility mangling algorithm (tested on MSVC ver. 19.35; toolset ver. 143); - IR emitting fixed on using a subobject as a template argument when the corresponding template parameter is used in an lvalue context; - `noundef` attribute and opaque pointers in `template-arguments` test; - analysis for C++17 mode is turned off for templates in `warn-bool-conversion` test; in C++17 and C++20 mode, array reference used as a template argument of pointer type produces template argument of UncommonValue type, and `BuildExpressionFromNonTypeTemplateArgumentValue` makes `OpaqueValueExpr` for it, and `DiagnoseAlwaysNonNullPointer` cannot see through it; despite of "These cases should not warn" comment, I'm not sure about correct behavior; I'd expect a suggestion to replace `if` by `if constexpr`; - `temp.arg.nontype/p1.cpp` and `dr18xx.cpp` tests fixed.
2024-01-21 23:28:57 +03:00
case TemplateArgument::StructuralValue:
return getSourceStructuralValueExpression()->getSourceRange();
case TemplateArgument::Pack:
case TemplateArgument::Null:
return SourceRange();
}
llvm_unreachable("Invalid TemplateArgument Kind!");
}
template <typename T>
static const T &DiagTemplateArg(const T &DB, const TemplateArgument &Arg) {
switch (Arg.getKind()) {
case TemplateArgument::Null:
// This is bad, but not as bad as crashing because of argument
// count mismatches.
return DB << "(null template argument)";
case TemplateArgument::Type:
return DB << Arg.getAsType();
case TemplateArgument::Declaration:
return DB << Arg.getAsDecl();
case TemplateArgument::NullPtr:
return DB << "nullptr";
case TemplateArgument::Integral:
return DB << toString(Arg.getAsIntegral(), 10);
[c++20] P1907R1: Support for generalized non-type template arguments of scalar type. (#78041) Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and reverted because a dependency commit was reverted, then committed again as 4b574008aef5a7235c1f894ab065fe300d26e786 and reverted again because "dependency commit" 5a391d38ac6c561ba908334d427f26124ed9132e was reverted. But it doesn't seem that 5a391d38ac6c was a real dependency for this. This commit incorporates 4b574008aef5a7235c1f894ab065fe300d26e786 and 18e093faf726d15f210ab4917142beec51848258 by Richard Smith (@zygoloid), with some minor fixes, most notably: - `UncommonValue` renamed to `StructuralValue` - `VK_PRValue` instead of `VK_RValue` as default kind in lvalue and member pointer handling branch in `BuildExpressionFromNonTypeTemplateArgumentValue`; - handling of `StructuralValue` in `IsTypeDeclaredInsideVisitor`; - filling in `SugaredConverted` along with `CanonicalConverted` parameter in `Sema::CheckTemplateArgument`; - minor cleanup in `TemplateInstantiator::transformNonTypeTemplateParmRef`; - `TemplateArgument` constructors refactored; - `ODRHash` calculation for `UncommonValue`; - USR generation for `UncommonValue`; - more correct MS compatibility mangling algorithm (tested on MSVC ver. 19.35; toolset ver. 143); - IR emitting fixed on using a subobject as a template argument when the corresponding template parameter is used in an lvalue context; - `noundef` attribute and opaque pointers in `template-arguments` test; - analysis for C++17 mode is turned off for templates in `warn-bool-conversion` test; in C++17 and C++20 mode, array reference used as a template argument of pointer type produces template argument of UncommonValue type, and `BuildExpressionFromNonTypeTemplateArgumentValue` makes `OpaqueValueExpr` for it, and `DiagnoseAlwaysNonNullPointer` cannot see through it; despite of "These cases should not warn" comment, I'm not sure about correct behavior; I'd expect a suggestion to replace `if` by `if constexpr`; - `temp.arg.nontype/p1.cpp` and `dr18xx.cpp` tests fixed.
2024-01-21 23:28:57 +03:00
case TemplateArgument::StructuralValue: {
// FIXME: We're guessing at LangOptions!
SmallString<32> Str;
llvm::raw_svector_ostream OS(Str);
LangOptions LangOpts;
LangOpts.CPlusPlus = true;
PrintingPolicy Policy(LangOpts);
Arg.getAsStructuralValue().printPretty(OS, Policy,
Arg.getStructuralValueType());
return DB << OS.str();
}
case TemplateArgument::Template:
return DB << Arg.getAsTemplate();
case TemplateArgument::TemplateExpansion:
return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
case TemplateArgument::Expression:
// FIXME: Support printing expressions as canonical
return DB << Arg.getAsExpr();
case TemplateArgument::Pack: {
// FIXME: We're guessing at LangOptions!
SmallString<32> Str;
llvm::raw_svector_ostream OS(Str);
LangOptions LangOpts;
LangOpts.CPlusPlus = true;
PrintingPolicy Policy(LangOpts);
Arg.print(Policy, OS, /*IncludeType*/ true);
return DB << OS.str();
}
}
llvm_unreachable("Invalid TemplateArgument Kind!");
}
const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
const TemplateArgument &Arg) {
return DiagTemplateArg(DB, Arg);
}
clang::TemplateArgumentLocInfo::TemplateArgumentLocInfo(
ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc) {
TemplateTemplateArgLocInfo *Template = new (Ctx) TemplateTemplateArgLocInfo;
Template->Qualifier = QualifierLoc.getNestedNameSpecifier();
Template->QualifierLocData = QualifierLoc.getOpaqueData();
Template->TemplateNameLoc = TemplateNameLoc;
Template->EllipsisLoc = EllipsisLoc;
Pointer = Template;
}
const ASTTemplateArgumentListInfo *
ASTTemplateArgumentListInfo::Create(const ASTContext &C,
const TemplateArgumentListInfo &List) {
std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(List.size());
void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo));
return new (Mem) ASTTemplateArgumentListInfo(List);
}
const ASTTemplateArgumentListInfo *
ASTTemplateArgumentListInfo::Create(const ASTContext &C,
const ASTTemplateArgumentListInfo *List) {
if (!List)
return nullptr;
std::size_t size =
totalSizeToAlloc<TemplateArgumentLoc>(List->getNumTemplateArgs());
void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo));
return new (Mem) ASTTemplateArgumentListInfo(List);
}
ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
const TemplateArgumentListInfo &Info) {
LAngleLoc = Info.getLAngleLoc();
RAngleLoc = Info.getRAngleLoc();
NumTemplateArgs = Info.size();
TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>();
Revert "Following up on PR48517, fix handling of template arguments that refer" Combined with 'da98651 - Revert "DR2064: decltype(E) is only a dependent', this change (5a391d3) caused verifier errors when building Chromium. See https://crbug.com/1168494#c1 for a reproducer. Additionally it reverts changes that were dependent on this one, see below. > Following up on PR48517, fix handling of template arguments that refer > to dependent declarations. > > Treat an id-expression that names a local variable in a templated > function as being instantiation-dependent. > > This addresses a language defect whereby a reference to a dependent > declaration can be formed without any construct being value-dependent. > Fixing that through value-dependence turns out to be problematic, so > instead this patch takes the approach (proposed on the core reflector) > of allowing the use of pointers or references to (but not values of) > dependent declarations inside value-dependent expressions, and instead > treating template arguments as dependent if they evaluate to a constant > involving such dependent declarations. > > This ends up affecting a bunch of OpenMP tests, due to OpenMP > imprecisely handling instantiation-dependent constructs, bailing out > early instead of processing dependent constructs to the extent possible > when handling the template. > > Previously committed as 8c1f2d15b826591cdf6bd6b468b8a7d23377b29e, and > reverted because a dependency commit was reverted. This reverts commit 5a391d38ac6c561ba908334d427f26124ed9132e. It also restores clang/test/SemaCXX/coroutines.cpp to its state before da986511fb9da1a46a0ca4dba2e49e2426036303. Revert "[c++20] P1907R1: Support for generalized non-type template arguments of scalar type." > Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and > reverted because a dependency commit was reverted. This incorporates the > following follow-on commits that were also reverted: > > 7e84aa1b81e72d44bcc58ffe1731bfc7abb73ce0 by Simon Pilgrim > ed13d8c66781b50ff007cb089c5905f9bb9e8af2 by me > 95c7b6cadbc9a3d4376ef44edbeb3c8bb5b8d7fc by Sam McCall > 430d5d8429473c2b10b109991d7577a3cea41140 by Dave Zarzycki This reverts commit 4b574008aef5a7235c1f894ab065fe300d26e786. Revert "[msabi] Mangle a template argument referring to array-to-pointer decay" > [msabi] Mangle a template argument referring to array-to-pointer decay > applied to an array the same as the array itself. > > This follows MS ABI, and corrects a regression from the implementation > of generalized non-type template parameters, where we "forgot" how to > mangle this case. This reverts commit 18e093faf726d15f210ab4917142beec51848258.
2021-01-20 15:25:33 +01:00
for (unsigned i = 0; i != NumTemplateArgs; ++i)
new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
}
ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
const ASTTemplateArgumentListInfo *Info) {
LAngleLoc = Info->getLAngleLoc();
RAngleLoc = Info->getRAngleLoc();
NumTemplateArgs = Info->getNumTemplateArgs();
TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>();
for (unsigned i = 0; i != NumTemplateArgs; ++i)
new (&ArgBuffer[i]) TemplateArgumentLoc((*Info)[i]);
}
void ASTTemplateKWAndArgsInfo::initializeFrom(
SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
TemplateArgumentLoc *OutArgArray) {
this->TemplateKWLoc = TemplateKWLoc;
LAngleLoc = Info.getLAngleLoc();
RAngleLoc = Info.getRAngleLoc();
NumTemplateArgs = Info.size();
Revert "Following up on PR48517, fix handling of template arguments that refer" Combined with 'da98651 - Revert "DR2064: decltype(E) is only a dependent', this change (5a391d3) caused verifier errors when building Chromium. See https://crbug.com/1168494#c1 for a reproducer. Additionally it reverts changes that were dependent on this one, see below. > Following up on PR48517, fix handling of template arguments that refer > to dependent declarations. > > Treat an id-expression that names a local variable in a templated > function as being instantiation-dependent. > > This addresses a language defect whereby a reference to a dependent > declaration can be formed without any construct being value-dependent. > Fixing that through value-dependence turns out to be problematic, so > instead this patch takes the approach (proposed on the core reflector) > of allowing the use of pointers or references to (but not values of) > dependent declarations inside value-dependent expressions, and instead > treating template arguments as dependent if they evaluate to a constant > involving such dependent declarations. > > This ends up affecting a bunch of OpenMP tests, due to OpenMP > imprecisely handling instantiation-dependent constructs, bailing out > early instead of processing dependent constructs to the extent possible > when handling the template. > > Previously committed as 8c1f2d15b826591cdf6bd6b468b8a7d23377b29e, and > reverted because a dependency commit was reverted. This reverts commit 5a391d38ac6c561ba908334d427f26124ed9132e. It also restores clang/test/SemaCXX/coroutines.cpp to its state before da986511fb9da1a46a0ca4dba2e49e2426036303. Revert "[c++20] P1907R1: Support for generalized non-type template arguments of scalar type." > Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and > reverted because a dependency commit was reverted. This incorporates the > following follow-on commits that were also reverted: > > 7e84aa1b81e72d44bcc58ffe1731bfc7abb73ce0 by Simon Pilgrim > ed13d8c66781b50ff007cb089c5905f9bb9e8af2 by me > 95c7b6cadbc9a3d4376ef44edbeb3c8bb5b8d7fc by Sam McCall > 430d5d8429473c2b10b109991d7577a3cea41140 by Dave Zarzycki This reverts commit 4b574008aef5a7235c1f894ab065fe300d26e786. Revert "[msabi] Mangle a template argument referring to array-to-pointer decay" > [msabi] Mangle a template argument referring to array-to-pointer decay > applied to an array the same as the array itself. > > This follows MS ABI, and corrects a regression from the implementation > of generalized non-type template parameters, where we "forgot" how to > mangle this case. This reverts commit 18e093faf726d15f210ab4917142beec51848258.
2021-01-20 15:25:33 +01:00
for (unsigned i = 0; i != NumTemplateArgs; ++i)
new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
}
void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
assert(TemplateKWLoc.isValid());
LAngleLoc = SourceLocation();
RAngleLoc = SourceLocation();
this->TemplateKWLoc = TemplateKWLoc;
NumTemplateArgs = 0;
}
Revert "Following up on PR48517, fix handling of template arguments that refer" Combined with 'da98651 - Revert "DR2064: decltype(E) is only a dependent', this change (5a391d3) caused verifier errors when building Chromium. See https://crbug.com/1168494#c1 for a reproducer. Additionally it reverts changes that were dependent on this one, see below. > Following up on PR48517, fix handling of template arguments that refer > to dependent declarations. > > Treat an id-expression that names a local variable in a templated > function as being instantiation-dependent. > > This addresses a language defect whereby a reference to a dependent > declaration can be formed without any construct being value-dependent. > Fixing that through value-dependence turns out to be problematic, so > instead this patch takes the approach (proposed on the core reflector) > of allowing the use of pointers or references to (but not values of) > dependent declarations inside value-dependent expressions, and instead > treating template arguments as dependent if they evaluate to a constant > involving such dependent declarations. > > This ends up affecting a bunch of OpenMP tests, due to OpenMP > imprecisely handling instantiation-dependent constructs, bailing out > early instead of processing dependent constructs to the extent possible > when handling the template. > > Previously committed as 8c1f2d15b826591cdf6bd6b468b8a7d23377b29e, and > reverted because a dependency commit was reverted. This reverts commit 5a391d38ac6c561ba908334d427f26124ed9132e. It also restores clang/test/SemaCXX/coroutines.cpp to its state before da986511fb9da1a46a0ca4dba2e49e2426036303. Revert "[c++20] P1907R1: Support for generalized non-type template arguments of scalar type." > Previously committed as 9e08e51a20d0d2b1c5724bb17e969d036fced4cd, and > reverted because a dependency commit was reverted. This incorporates the > following follow-on commits that were also reverted: > > 7e84aa1b81e72d44bcc58ffe1731bfc7abb73ce0 by Simon Pilgrim > ed13d8c66781b50ff007cb089c5905f9bb9e8af2 by me > 95c7b6cadbc9a3d4376ef44edbeb3c8bb5b8d7fc by Sam McCall > 430d5d8429473c2b10b109991d7577a3cea41140 by Dave Zarzycki This reverts commit 4b574008aef5a7235c1f894ab065fe300d26e786. Revert "[msabi] Mangle a template argument referring to array-to-pointer decay" > [msabi] Mangle a template argument referring to array-to-pointer decay > applied to an array the same as the array itself. > > This follows MS ABI, and corrects a regression from the implementation > of generalized non-type template parameters, where we "forgot" how to > mangle this case. This reverts commit 18e093faf726d15f210ab4917142beec51848258.
2021-01-20 15:25:33 +01:00
void ASTTemplateKWAndArgsInfo::initializeFrom(
SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
TemplateArgumentLoc *OutArgArray, TemplateArgumentDependence &Deps) {
this->TemplateKWLoc = TemplateKWLoc;
LAngleLoc = Info.getLAngleLoc();
RAngleLoc = Info.getRAngleLoc();
NumTemplateArgs = Info.size();
for (unsigned i = 0; i != NumTemplateArgs; ++i) {
Deps |= Info[i].getArgument().getDependence();
new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
}
}
void ASTTemplateKWAndArgsInfo::copyInto(const TemplateArgumentLoc *ArgArray,
TemplateArgumentListInfo &Info) const {
Info.setLAngleLoc(LAngleLoc);
Info.setRAngleLoc(RAngleLoc);
for (unsigned I = 0; I != NumTemplateArgs; ++I)
Info.addArgument(ArgArray[I]);
}