aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
authorGuillot Tony <tony.guillot@protonmail.com>2023-10-05 08:08:37 -0400
committerAaron Ballman <aaron@aaronballman.com>2023-10-05 08:11:02 -0400
commit5d78b78c853830516e734cfa64bfba70479e35dc (patch)
tree2e4862b41f81c5332b9158619418c37d126d6ed1 /clang/lib
parent58678d3bcf32bada15d6286dff4abfdbf40bfc21 (diff)
downloadllvm-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.cpp2
-rw-r--r--clang/lib/Sema/DeclSpec.cpp5
-rw-r--r--clang/lib/Sema/SemaDecl.cpp9
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp18
-rw-r--r--clang/lib/Sema/SemaType.cpp5
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;