|
11 | 11 | //===----------------------------------------------------------------------===// |
12 | 12 |
|
13 | 13 | #include "clang/AST/DeclCXX.h" |
| 14 | +#include "clang/AST/TemplateBase.h" |
14 | 15 | #include "clang/AST/Type.h" |
15 | 16 | #include "clang/Basic/DiagnosticParse.h" |
16 | 17 | #include "clang/Basic/DiagnosticSema.h" |
@@ -1947,6 +1948,7 @@ static std::optional<TypeTrait> StdNameToTypeTrait(StringRef Name) { |
1947 | 1948 | TypeTrait::UTT_IsCppTriviallyRelocatable) |
1948 | 1949 | .Case("is_replaceable", TypeTrait::UTT_IsReplaceable) |
1949 | 1950 | .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) |
| 1951 | + .Case("is_constructible", TypeTrait::TT_IsConstructible) |
1950 | 1952 | .Default(std::nullopt); |
1951 | 1953 | } |
1952 | 1954 |
|
@@ -1983,8 +1985,16 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) { |
1983 | 1985 | Trait = StdNameToTypeTrait(Name); |
1984 | 1986 | if (!Trait) |
1985 | 1987 | return std::nullopt; |
1986 | | - for (const auto &Arg : VD->getTemplateArgs().asArray()) |
1987 | | - Args.push_back(Arg.getAsType()); |
| 1988 | + for (const auto &Arg : VD->getTemplateArgs().asArray()) { |
| 1989 | + if (Arg.getKind() == TemplateArgument::ArgKind::Pack) { |
| 1990 | + for (const auto &InnerArg : Arg.pack_elements()) |
| 1991 | + Args.push_back(InnerArg.getAsType()); |
| 1992 | + } else if (Arg.getKind() == TemplateArgument::ArgKind::Type) { |
| 1993 | + Args.push_back(Arg.getAsType()); |
| 1994 | + } else { |
| 1995 | + llvm_unreachable("Unexpected kind"); |
| 1996 | + } |
| 1997 | + } |
1988 | 1998 | return {{Trait.value(), std::move(Args)}}; |
1989 | 1999 | } |
1990 | 2000 |
|
@@ -2257,6 +2267,60 @@ static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, |
2257 | 2267 | } |
2258 | 2268 | } |
2259 | 2269 |
|
| 2270 | +static void DiagnoseNonConstructibleReason( |
| 2271 | + Sema &SemaRef, SourceLocation Loc, |
| 2272 | + const llvm::SmallVector<clang::QualType, 1> &Ts) { |
| 2273 | + if (Ts.empty()) { |
| 2274 | + return; |
| 2275 | + } |
| 2276 | + |
| 2277 | + bool ContainsVoid = false; |
| 2278 | + for (const QualType &ArgTy : Ts) { |
| 2279 | + ContainsVoid |= ArgTy->isVoidType(); |
| 2280 | + } |
| 2281 | + |
| 2282 | + if (ContainsVoid) |
| 2283 | + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) |
| 2284 | + << diag::TraitNotSatisfiedReason::CVVoidType; |
| 2285 | + |
| 2286 | + QualType T = Ts[0]; |
| 2287 | + if (T->isFunctionType()) |
| 2288 | + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) |
| 2289 | + << diag::TraitNotSatisfiedReason::FunctionType; |
| 2290 | + |
| 2291 | + if (T->isIncompleteArrayType()) |
| 2292 | + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) |
| 2293 | + << diag::TraitNotSatisfiedReason::IncompleteArrayType; |
| 2294 | + |
| 2295 | + const CXXRecordDecl *D = T->getAsCXXRecordDecl(); |
| 2296 | + if (!D || D->isInvalidDecl() || !D->hasDefinition()) |
| 2297 | + return; |
| 2298 | + |
| 2299 | + llvm::BumpPtrAllocator OpaqueExprAllocator; |
| 2300 | + SmallVector<Expr *, 2> ArgExprs; |
| 2301 | + ArgExprs.reserve(Ts.size() - 1); |
| 2302 | + for (unsigned I = 1, N = Ts.size(); I != N; ++I) { |
| 2303 | + QualType ArgTy = Ts[I]; |
| 2304 | + if (ArgTy->isObjectType() || ArgTy->isFunctionType()) |
| 2305 | + ArgTy = SemaRef.Context.getRValueReferenceType(ArgTy); |
| 2306 | + ArgExprs.push_back( |
| 2307 | + new (OpaqueExprAllocator.Allocate<OpaqueValueExpr>()) |
| 2308 | + OpaqueValueExpr(Loc, ArgTy.getNonLValueExprType(SemaRef.Context), |
| 2309 | + Expr::getValueKindForType(ArgTy))); |
| 2310 | + } |
| 2311 | + |
| 2312 | + EnterExpressionEvaluationContext Unevaluated( |
| 2313 | + SemaRef, Sema::ExpressionEvaluationContext::Unevaluated); |
| 2314 | + Sema::ContextRAII TUContext(SemaRef, |
| 2315 | + SemaRef.Context.getTranslationUnitDecl()); |
| 2316 | + InitializedEntity To(InitializedEntity::InitializeTemporary(T)); |
| 2317 | + InitializationKind InitKind(InitializationKind::CreateDirect(Loc, Loc, Loc)); |
| 2318 | + InitializationSequence Init(SemaRef, To, InitKind, ArgExprs); |
| 2319 | + |
| 2320 | + Init.Diagnose(SemaRef, To, InitKind, ArgExprs); |
| 2321 | + SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; |
| 2322 | +} |
| 2323 | + |
2260 | 2324 | static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, |
2261 | 2325 | SourceLocation Loc, QualType T) { |
2262 | 2326 | SemaRef.Diag(Loc, diag::note_unsatisfied_trait) |
@@ -2296,6 +2360,9 @@ void Sema::DiagnoseTypeTraitDetails(const Expr *E) { |
2296 | 2360 | case UTT_IsTriviallyCopyable: |
2297 | 2361 | DiagnoseNonTriviallyCopyableReason(*this, E->getBeginLoc(), Args[0]); |
2298 | 2362 | break; |
| 2363 | + case TT_IsConstructible: |
| 2364 | + DiagnoseNonConstructibleReason(*this, E->getBeginLoc(), Args); |
| 2365 | + break; |
2299 | 2366 | default: |
2300 | 2367 | break; |
2301 | 2368 | } |
|
0 commit comments