diff options
author | Guillot Tony <tony.guillot@protonmail.com> | 2023-10-05 08:08:37 -0400 |
---|---|---|
committer | Aaron Ballman <aaron@aaronballman.com> | 2023-10-05 08:11:02 -0400 |
commit | 5d78b78c853830516e734cfa64bfba70479e35dc (patch) | |
tree | 2e4862b41f81c5332b9158619418c37d126d6ed1 /clang/lib | |
parent | 58678d3bcf32bada15d6286dff4abfdbf40bfc21 (diff) | |
download | llvm-5d78b78c853830516e734cfa64bfba70479e35dc.zip llvm-5d78b78c853830516e734cfa64bfba70479e35dc.tar.gz llvm-5d78b78c853830516e734cfa64bfba70479e35dc.tar.bz2 |
[C2X] N3007 Type inference for object definitions
This patches implements the auto keyword from the N3007 standard
specification.
This allows deducing the type of the variable like in C++:
```
auto nb = 1;
auto chr = 'A';
auto str = "String";
```
The list of statements which allows the usage of auto:
* Basic variables declarations (int, float, double, char, char*...)
* Macros declaring a variable with the auto type
The list of statements which will not work with the auto keyword:
* auto arrays
* sizeof(), alignas()
* auto parameters, auto return type
* auto as a struct/typedef member
* uninitialized auto variables
* auto in an union
* auto as a enum type specifier
* auto casts
* auto in an compound literals
Differential Revision: https://reviews.llvm.org/D133289
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/DeclSpec.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 18 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 5 |
5 files changed, 34 insertions, 5 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 9351594..bcc70c0 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4038,7 +4038,7 @@ void Parser::ParseDeclarationSpecifiers( isStorageClass = true; break; case tok::kw_auto: - if (getLangOpts().CPlusPlus11) { + if (getLangOpts().CPlusPlus11 || getLangOpts().C23) { if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc, PrevSpec, DiagID, Policy); diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 2d0d575..781f24c 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -1375,8 +1375,9 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { StorageClassSpecLoc = SourceLocation(); } // Diagnose if we've recovered from an ill-formed 'auto' storage class - // specifier in a pre-C++11 dialect of C++. - if (!S.getLangOpts().CPlusPlus11 && TypeSpecType == TST_auto) + // specifier in a pre-C++11 dialect of C++ or in a pre-C23 dialect of C. + if (!S.getLangOpts().CPlusPlus11 && !S.getLangOpts().C23 && + TypeSpecType == TST_auto) S.Diag(TSTLoc, diag::ext_auto_type_specifier); if (S.getLangOpts().CPlusPlus && !S.getLangOpts().CPlusPlus11 && StorageClassSpec == SCS_auto) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index fce56d2..d1dbe5f 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12863,6 +12863,15 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl, DeducedType *Deduced = Type->getContainedDeducedType(); assert(Deduced && "deduceVarTypeFromInitializer for non-deduced type"); + // Diagnose auto array declarations in C23, unless it's a supported extension. + if (getLangOpts().C23 && Type->isArrayType() && + !isa_and_present<StringLiteral, InitListExpr>(Init)) { + Diag(Range.getBegin(), diag::err_auto_not_allowed) + << (int)Deduced->getContainedAutoType()->getKeyword() + << /*in array decl*/ 23 << Range; + return QualType(); + } + // C++11 [dcl.spec.auto]p3 if (!Init) { assert(VDecl && "no init for init capture deduction?"); diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 69b857d..62fbd90 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -4842,9 +4842,25 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, return TDK_Success; } + // Make sure that we treat 'char[]' equaly as 'char*' in C23 mode. + auto *String = dyn_cast<StringLiteral>(Init); + if (getLangOpts().C23 && String && Type.getType()->isArrayType()) { + Diag(Type.getBeginLoc(), diag::ext_c23_auto_non_plain_identifier); + TypeLoc TL = TypeLoc(Init->getType(), Type.getOpaqueData()); + Result = SubstituteDeducedTypeTransform(*this, DependentResult).Apply(TL); + assert(!Result.isNull() && "substituting DependentTy can't fail"); + return TDK_Success; + } + + // Emit a warning if 'auto*' is used in pedantic and in C23 mode. + if (getLangOpts().C23 && Type.getType()->isPointerType()) { + Diag(Type.getBeginLoc(), diag::ext_c23_auto_non_plain_identifier); + } + auto *InitList = dyn_cast<InitListExpr>(Init); if (!getLangOpts().CPlusPlus && InitList) { - Diag(Init->getBeginLoc(), diag::err_auto_init_list_from_c); + Diag(Init->getBeginLoc(), diag::err_auto_init_list_from_c) + << (int)AT->getKeyword() << getLangOpts().C23; return TDK_AlreadyDiagnosed; } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 8f73268..068971f 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -9880,11 +9880,14 @@ QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) { DisallowedKind = 5; else if (T->isSizelessType()) DisallowedKind = 6; - else if (!T.isTriviallyCopyableType(Context)) + else if (!T.isTriviallyCopyableType(Context) && getLangOpts().CPlusPlus) // Some other non-trivially-copyable type (probably a C++ class) DisallowedKind = 7; else if (T->isBitIntType()) DisallowedKind = 8; + else if (getLangOpts().C23 && T->isUndeducedAutoType()) + // _Atomic auto is prohibited in C23 + DisallowedKind = 9; if (DisallowedKind != -1) { Diag(Loc, diag::err_atomic_specifier_bad_type) << DisallowedKind << T; |