|
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