|
11 | 11 | //===----------------------------------------------------------------------===//
|
12 | 12 |
|
13 | 13 | #include "clang/AST/DeclCXX.h"
|
| 14 | +#include "clang/AST/TemplateBase.h" |
14 | 15 | #include "clang/AST/Type.h"
|
| 16 | +#include "clang/Basic/DiagnosticIDs.h" |
15 | 17 | #include "clang/Basic/DiagnosticParse.h"
|
16 | 18 | #include "clang/Basic/DiagnosticSema.h"
|
17 | 19 | #include "clang/Basic/TypeTraits.h"
|
@@ -1963,6 +1965,7 @@ static std::optional<TypeTrait> StdNameToTypeTrait(StringRef Name) {
|
1963 | 1965 | .Case("is_assignable", TypeTrait::BTT_IsAssignable)
|
1964 | 1966 | .Case("is_empty", TypeTrait::UTT_IsEmpty)
|
1965 | 1967 | .Case("is_standard_layout", TypeTrait::UTT_IsStandardLayout)
|
| 1968 | + .Case("is_constructible", TypeTrait::TT_IsConstructible) |
1966 | 1969 | .Default(std::nullopt);
|
1967 | 1970 | }
|
1968 | 1971 |
|
@@ -1999,8 +2002,16 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) {
|
1999 | 2002 | Trait = StdNameToTypeTrait(Name);
|
2000 | 2003 | if (!Trait)
|
2001 | 2004 | return std::nullopt;
|
2002 |
| - for (const auto &Arg : VD->getTemplateArgs().asArray()) |
2003 |
| - Args.push_back(Arg.getAsType()); |
| 2005 | + for (const auto &Arg : VD->getTemplateArgs().asArray()) { |
| 2006 | + if (Arg.getKind() == TemplateArgument::ArgKind::Pack) { |
| 2007 | + for (const auto &InnerArg : Arg.pack_elements()) |
| 2008 | + Args.push_back(InnerArg.getAsType()); |
| 2009 | + } else if (Arg.getKind() == TemplateArgument::ArgKind::Type) { |
| 2010 | + Args.push_back(Arg.getAsType()); |
| 2011 | + } else { |
| 2012 | + llvm_unreachable("Unexpected kind"); |
| 2013 | + } |
| 2014 | + } |
2004 | 2015 | return {{Trait.value(), std::move(Args)}};
|
2005 | 2016 | }
|
2006 | 2017 |
|
@@ -2273,6 +2284,60 @@ static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef,
|
2273 | 2284 | }
|
2274 | 2285 | }
|
2275 | 2286 |
|
| 2287 | +static void DiagnoseNonConstructibleReason( |
| 2288 | + Sema &SemaRef, SourceLocation Loc, |
| 2289 | + const llvm::SmallVector<clang::QualType, 1> &Ts) { |
| 2290 | + if (Ts.empty()) { |
| 2291 | + return; |
| 2292 | + } |
| 2293 | + |
| 2294 | + bool ContainsVoid = false; |
| 2295 | + for (const QualType &ArgTy : Ts) { |
| 2296 | + ContainsVoid |= ArgTy->isVoidType(); |
| 2297 | + } |
| 2298 | + |
| 2299 | + if (ContainsVoid) |
| 2300 | + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) |
| 2301 | + << diag::TraitNotSatisfiedReason::CVVoidType; |
| 2302 | + |
| 2303 | + QualType T = Ts[0]; |
| 2304 | + if (T->isFunctionType()) |
| 2305 | + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) |
| 2306 | + << diag::TraitNotSatisfiedReason::FunctionType; |
| 2307 | + |
| 2308 | + if (T->isIncompleteArrayType()) |
| 2309 | + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) |
| 2310 | + << diag::TraitNotSatisfiedReason::IncompleteArrayType; |
| 2311 | + |
| 2312 | + const CXXRecordDecl *D = T->getAsCXXRecordDecl(); |
| 2313 | + if (!D || D->isInvalidDecl() || !D->hasDefinition()) |
| 2314 | + return; |
| 2315 | + |
| 2316 | + llvm::BumpPtrAllocator OpaqueExprAllocator; |
| 2317 | + SmallVector<Expr *, 2> ArgExprs; |
| 2318 | + ArgExprs.reserve(Ts.size() - 1); |
| 2319 | + for (unsigned I = 1, N = Ts.size(); I != N; ++I) { |
| 2320 | + QualType ArgTy = Ts[I]; |
| 2321 | + if (ArgTy->isObjectType() || ArgTy->isFunctionType()) |
| 2322 | + ArgTy = SemaRef.Context.getRValueReferenceType(ArgTy); |
| 2323 | + ArgExprs.push_back( |
| 2324 | + new (OpaqueExprAllocator.Allocate<OpaqueValueExpr>()) |
| 2325 | + OpaqueValueExpr(Loc, ArgTy.getNonLValueExprType(SemaRef.Context), |
| 2326 | + Expr::getValueKindForType(ArgTy))); |
| 2327 | + } |
| 2328 | + |
| 2329 | + EnterExpressionEvaluationContext Unevaluated( |
| 2330 | + SemaRef, Sema::ExpressionEvaluationContext::Unevaluated); |
| 2331 | + Sema::ContextRAII TUContext(SemaRef, |
| 2332 | + SemaRef.Context.getTranslationUnitDecl()); |
| 2333 | + InitializedEntity To(InitializedEntity::InitializeTemporary(T)); |
| 2334 | + InitializationKind InitKind(InitializationKind::CreateDirect(Loc, Loc, Loc)); |
| 2335 | + InitializationSequence Init(SemaRef, To, InitKind, ArgExprs); |
| 2336 | + |
| 2337 | + Init.Diagnose(SemaRef, To, InitKind, ArgExprs); |
| 2338 | + SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; |
| 2339 | +} |
| 2340 | + |
2276 | 2341 | static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef,
|
2277 | 2342 | SourceLocation Loc, QualType T) {
|
2278 | 2343 | SemaRef.Diag(Loc, diag::note_unsatisfied_trait)
|
@@ -2559,6 +2624,9 @@ void Sema::DiagnoseTypeTraitDetails(const Expr *E) {
|
2559 | 2624 | case UTT_IsStandardLayout:
|
2560 | 2625 | DiagnoseNonStandardLayoutReason(*this, E->getBeginLoc(), Args[0]);
|
2561 | 2626 | break;
|
| 2627 | + case TT_IsConstructible: |
| 2628 | + DiagnoseNonConstructibleReason(*this, E->getBeginLoc(), Args); |
| 2629 | + break; |
2562 | 2630 | default:
|
2563 | 2631 | break;
|
2564 | 2632 | }
|
|
0 commit comments