2018-04-06 06:15:42 +08:00
|
|
|
//===--- DeclSpec.cpp - Declaration Specifier Semantic Analysis -----------===//
|
2006-08-04 12:39:53 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2006-08-04 12:39:53 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2006-11-08 14:54:53 +08:00
|
|
|
// This file implements semantic analysis for declaration specifiers.
|
2006-08-04 12:39:53 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-08-21 02:27:03 +08:00
|
|
|
#include "clang/Sema/DeclSpec.h"
|
2011-02-25 01:54:50 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2013-10-08 08:58:57 +08:00
|
|
|
#include "clang/AST/DeclCXX.h"
|
2011-06-25 08:56:27 +08:00
|
|
|
#include "clang/AST/Expr.h"
|
2016-02-02 01:42:01 +08:00
|
|
|
#include "clang/AST/LocInfoType.h"
|
2011-02-24 08:17:56 +08:00
|
|
|
#include "clang/AST/TypeLoc.h"
|
2006-08-04 13:25:55 +08:00
|
|
|
#include "clang/Basic/LangOptions.h"
|
[PowerPC] Initial VSX intrinsic support, with min/max for vector double
Now that we have initial support for VSX, we can begin adding
intrinsics for programmer access to VSX instructions. This patch
performs the necessary enablement in the front end, and tests it by
implementing intrinsics for minimum and maximum using the vector
double data type.
The main change in the front end is to no longer disallow "vector" and
"double" in the same declaration (lib/Sema/DeclSpec.cpp), but "vector"
and "long double" must still be disallowed. The new intrinsics are
accessed via vec_max and vec_min with changes in
lib/Headers/altivec.h. Note that for v4f32, we already access
corresponding VMX builtins, but with VSX enabled we should use the
forms that allow all 64 vector registers.
The new built-ins are defined in include/clang/Basic/BuiltinsPPC.def.
I've added a new test in test/CodeGen/builtins-ppc-vsx.c that is
similar to, but much smaller than, builtins-ppc-altivec.c. This
allows us to test VSX IR generation without duplicating CHECK lines
for the existing bazillion Altivec tests.
Since vector double is now legal when VSX is available, I've modified
the error message, and changed where we test for it and for vector
long double, since the target machine isn't visible in the old place.
This serendipitously removed a not-pertinent warning about 'long'
being deprecated when used with 'vector', when "vector long double" is
encountered and we just want to issue an error. The existing tests
test/Parser/altivec.c and test/Parser/cxx-altivec.cpp have been
updated accordingly, and I've added test/Parser/vsx.c to verify that
"vector double" is now legitimate with VSX enabled.
There is a companion patch for LLVM.
llvm-svn: 220989
2014-11-01 03:19:24 +08:00
|
|
|
#include "clang/Basic/TargetInfo.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/Sema/ParsedTemplate.h"
|
|
|
|
#include "clang/Sema/Sema.h"
|
|
|
|
#include "clang/Sema/SemaDiagnostic.h"
|
2009-01-21 03:11:22 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2013-04-13 06:46:28 +08:00
|
|
|
#include "llvm/ADT/SmallString.h"
|
Introduce a representation for types that we referred to via a
qualified name, e.g.,
foo::x
so that we retain the nested-name-specifier as written in the source
code and can reproduce that qualified name when printing the types
back (e.g., in diagnostics). This is PR3493, which won't be complete
until finished the other tasks mentioned near the end of this commit.
The parser's representation of nested-name-specifiers, CXXScopeSpec,
is now a bit fatter, because it needs to contain the scopes that
precede each '::' and keep track of whether the global scoping
operator '::' was at the beginning. For example, we need to keep track
of the leading '::', 'foo', and 'bar' in
::foo::bar::x
The Action's CXXScopeTy * is no longer a DeclContext *. It's now the
opaque version of the new NestedNameSpecifier, which contains a single
component of a nested-name-specifier (either a DeclContext * or a Type
*, bitmangled).
The new sugar type QualifiedNameType composes a sequence of
NestedNameSpecifiers with a representation of the type we're actually
referring to. At present, we only build QualifiedNameType nodes within
Sema::getTypeName. This will be extended to other type-constructing
actions (e.g., ActOnClassTemplateId).
Also on the way: QualifiedDeclRefExprs will also store a sequence of
NestedNameSpecifiers, so that we can print out the property
nested-name-specifier. I expect to also use this for handling
dependent names like Fibonacci<I - 1>::value.
llvm-svn: 67265
2009-03-19 08:18:19 +08:00
|
|
|
#include <cstring>
|
2018-04-06 05:09:03 +08:00
|
|
|
using namespace clang;
|
2008-11-22 16:32:36 +08:00
|
|
|
|
2018-04-06 06:15:42 +08:00
|
|
|
|
2009-11-11 03:49:08 +08:00
|
|
|
void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) {
|
|
|
|
assert(TemplateId && "NULL template-id annotation?");
|
2017-12-30 12:15:27 +08:00
|
|
|
Kind = UnqualifiedIdKind::IK_TemplateId;
|
2009-11-11 03:49:08 +08:00
|
|
|
this->TemplateId = TemplateId;
|
|
|
|
StartLocation = TemplateId->TemplateNameLoc;
|
|
|
|
EndLocation = TemplateId->RAngleLoc;
|
|
|
|
}
|
|
|
|
|
2010-01-14 01:31:36 +08:00
|
|
|
void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) {
|
|
|
|
assert(TemplateId && "NULL template-id annotation?");
|
2017-12-30 12:15:27 +08:00
|
|
|
Kind = UnqualifiedIdKind::IK_ConstructorTemplateId;
|
2010-01-14 01:31:36 +08:00
|
|
|
this->TemplateId = TemplateId;
|
|
|
|
StartLocation = TemplateId->TemplateNameLoc;
|
|
|
|
EndLocation = TemplateId->RAngleLoc;
|
|
|
|
}
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc,
|
2011-02-24 08:17:56 +08:00
|
|
|
TypeLoc TL, SourceLocation ColonColonLoc) {
|
2011-03-01 07:58:31 +08:00
|
|
|
Builder.Extend(Context, TemplateKWLoc, TL, ColonColonLoc);
|
2011-02-24 08:17:56 +08:00
|
|
|
if (Range.getBegin().isInvalid())
|
|
|
|
Range.setBegin(TL.getBeginLoc());
|
|
|
|
Range.setEnd(ColonColonLoc);
|
2011-02-25 01:54:50 +08:00
|
|
|
|
2011-03-01 07:58:31 +08:00
|
|
|
assert(Range == Builder.getSourceRange() &&
|
2011-02-25 01:54:50 +08:00
|
|
|
"NestedNameSpecifierLoc range computation incorrect");
|
2011-02-24 08:17:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier,
|
2018-07-31 03:24:48 +08:00
|
|
|
SourceLocation IdentifierLoc,
|
2011-02-24 08:17:56 +08:00
|
|
|
SourceLocation ColonColonLoc) {
|
2011-03-01 07:58:31 +08:00
|
|
|
Builder.Extend(Context, Identifier, IdentifierLoc, ColonColonLoc);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-02-24 08:17:56 +08:00
|
|
|
if (Range.getBegin().isInvalid())
|
|
|
|
Range.setBegin(IdentifierLoc);
|
|
|
|
Range.setEnd(ColonColonLoc);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-03-01 07:58:31 +08:00
|
|
|
assert(Range == Builder.getSourceRange() &&
|
2011-02-25 01:54:50 +08:00
|
|
|
"NestedNameSpecifierLoc range computation incorrect");
|
2011-02-24 08:17:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace,
|
2018-07-31 03:24:48 +08:00
|
|
|
SourceLocation NamespaceLoc,
|
2011-02-24 08:17:56 +08:00
|
|
|
SourceLocation ColonColonLoc) {
|
2011-03-01 07:58:31 +08:00
|
|
|
Builder.Extend(Context, Namespace, NamespaceLoc, ColonColonLoc);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-02-24 08:17:56 +08:00
|
|
|
if (Range.getBegin().isInvalid())
|
|
|
|
Range.setBegin(NamespaceLoc);
|
|
|
|
Range.setEnd(ColonColonLoc);
|
2011-02-25 01:54:50 +08:00
|
|
|
|
2011-03-01 07:58:31 +08:00
|
|
|
assert(Range == Builder.getSourceRange() &&
|
2011-02-25 01:54:50 +08:00
|
|
|
"NestedNameSpecifierLoc range computation incorrect");
|
2011-02-24 08:17:56 +08:00
|
|
|
}
|
|
|
|
|
2011-02-24 10:36:08 +08:00
|
|
|
void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
|
2018-07-31 03:24:48 +08:00
|
|
|
SourceLocation AliasLoc,
|
2011-02-24 10:36:08 +08:00
|
|
|
SourceLocation ColonColonLoc) {
|
2011-03-01 07:58:31 +08:00
|
|
|
Builder.Extend(Context, Alias, AliasLoc, ColonColonLoc);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-02-24 10:36:08 +08:00
|
|
|
if (Range.getBegin().isInvalid())
|
|
|
|
Range.setBegin(AliasLoc);
|
|
|
|
Range.setEnd(ColonColonLoc);
|
2011-02-25 01:54:50 +08:00
|
|
|
|
2011-03-01 07:58:31 +08:00
|
|
|
assert(Range == Builder.getSourceRange() &&
|
2011-02-25 01:54:50 +08:00
|
|
|
"NestedNameSpecifierLoc range computation incorrect");
|
2011-02-24 10:36:08 +08:00
|
|
|
}
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
void CXXScopeSpec::MakeGlobal(ASTContext &Context,
|
2011-02-24 08:17:56 +08:00
|
|
|
SourceLocation ColonColonLoc) {
|
2011-03-01 07:58:31 +08:00
|
|
|
Builder.MakeGlobal(Context, ColonColonLoc);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-03-01 07:58:31 +08:00
|
|
|
Range = SourceRange(ColonColonLoc);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-03-01 07:58:31 +08:00
|
|
|
assert(Range == Builder.getSourceRange() &&
|
2011-02-25 01:54:50 +08:00
|
|
|
"NestedNameSpecifierLoc range computation incorrect");
|
|
|
|
}
|
|
|
|
|
2014-09-26 08:28:20 +08:00
|
|
|
void CXXScopeSpec::MakeSuper(ASTContext &Context, CXXRecordDecl *RD,
|
|
|
|
SourceLocation SuperLoc,
|
|
|
|
SourceLocation ColonColonLoc) {
|
|
|
|
Builder.MakeSuper(Context, RD, SuperLoc, ColonColonLoc);
|
|
|
|
|
|
|
|
Range.setBegin(SuperLoc);
|
|
|
|
Range.setEnd(ColonColonLoc);
|
|
|
|
|
|
|
|
assert(Range == Builder.getSourceRange() &&
|
|
|
|
"NestedNameSpecifierLoc range computation incorrect");
|
|
|
|
}
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
void CXXScopeSpec::MakeTrivial(ASTContext &Context,
|
2011-02-25 01:54:50 +08:00
|
|
|
NestedNameSpecifier *Qualifier, SourceRange R) {
|
2011-03-01 07:58:31 +08:00
|
|
|
Builder.MakeTrivial(Context, Qualifier, R);
|
2011-02-25 01:54:50 +08:00
|
|
|
Range = R;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CXXScopeSpec::Adopt(NestedNameSpecifierLoc Other) {
|
|
|
|
if (!Other) {
|
|
|
|
Range = SourceRange();
|
2011-03-01 07:58:31 +08:00
|
|
|
Builder.Clear();
|
2011-02-25 01:54:50 +08:00
|
|
|
return;
|
|
|
|
}
|
2011-03-01 07:58:31 +08:00
|
|
|
|
2011-02-25 01:54:50 +08:00
|
|
|
Range = Other.getSourceRange();
|
2011-03-01 07:58:31 +08:00
|
|
|
Builder.Adopt(Other);
|
2011-02-25 01:54:50 +08:00
|
|
|
}
|
|
|
|
|
2011-07-06 14:57:57 +08:00
|
|
|
SourceLocation CXXScopeSpec::getLastQualifierNameLoc() const {
|
|
|
|
if (!Builder.getRepresentation())
|
2018-04-06 06:15:42 +08:00
|
|
|
return SourceLocation();
|
2011-07-06 14:57:57 +08:00
|
|
|
return Builder.getTemporary().getLocalBeginLoc();
|
|
|
|
}
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
NestedNameSpecifierLoc
|
2011-02-25 10:25:35 +08:00
|
|
|
CXXScopeSpec::getWithLocInContext(ASTContext &Context) const {
|
2011-03-04 05:48:55 +08:00
|
|
|
if (!Builder.getRepresentation())
|
2018-04-06 06:15:42 +08:00
|
|
|
return NestedNameSpecifierLoc();
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-03-01 07:58:31 +08:00
|
|
|
return Builder.getWithLocInContext(Context);
|
2011-02-24 08:17:56 +08:00
|
|
|
}
|
|
|
|
|
2009-01-21 03:11:22 +08:00
|
|
|
/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
|
|
|
|
/// "TheDeclarator" is the declarator that this will be added to.
|
2012-10-05 05:42:10 +08:00
|
|
|
DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto,
|
2012-07-31 05:30:52 +08:00
|
|
|
bool isAmbiguous,
|
2012-10-05 05:42:10 +08:00
|
|
|
SourceLocation LParenLoc,
|
2014-02-27 06:27:52 +08:00
|
|
|
ParamInfo *Params,
|
|
|
|
unsigned NumParams,
|
2012-10-05 05:42:10 +08:00
|
|
|
SourceLocation EllipsisLoc,
|
|
|
|
SourceLocation RParenLoc,
|
2011-01-26 11:43:54 +08:00
|
|
|
bool RefQualifierIsLvalueRef,
|
|
|
|
SourceLocation RefQualifierLoc,
|
2011-07-14 05:47:47 +08:00
|
|
|
SourceLocation MutableLoc,
|
2011-03-06 06:42:13 +08:00
|
|
|
ExceptionSpecificationType
|
|
|
|
ESpecType,
|
2015-08-26 12:19:36 +08:00
|
|
|
SourceRange ESpecRange,
|
2010-08-24 13:47:05 +08:00
|
|
|
ParsedType *Exceptions,
|
2009-05-30 02:02:33 +08:00
|
|
|
SourceRange *ExceptionRanges,
|
2009-04-30 01:30:04 +08:00
|
|
|
unsigned NumExceptions,
|
2011-03-06 06:42:13 +08:00
|
|
|
Expr *NoexceptExpr,
|
2014-11-14 04:01:57 +08:00
|
|
|
CachedTokens *ExceptionSpecTokens,
|
Store decls in prototypes on the declarator instead of in the AST
This saves two pointers from FunctionDecl that were being used for some
rare and questionable C-only functionality. The DeclsInPrototypeScope
ArrayRef was added in r151712 in order to parse this kind of C code:
enum e {x, y};
int f(enum {y, x} n) {
return x; // should return 1, not 0
}
The challenge is that we parse 'int f(enum {y, x} n)' it its own
function prototype scope that gets popped before we build the
FunctionDecl for 'f'. The original change was doing two questionable
things:
1. Saving all tag decls introduced in prototype scope on a TU-global
Sema variable. This is problematic when you have cases like this, where
'x' and 'y' shouldn't be visible in 'f':
void f(void (*fp)(enum { x, y } e)) { /* no x */ }
This patch fixes that, so now 'f' can't see 'x', which is consistent
with GCC.
2. Storing the decls in FunctionDecl in ActOnFunctionDeclarator so that
they could be used in ActOnStartOfFunctionDef. This is just an
inefficient way to move information around. The AST lives forever, but
the list of non-parameter decls in prototype scope is short lived.
Moving these things to the Declarator solves both of these issues.
Reviewers: rsmith
Subscribers: jmolloy, cfe-commits
Differential Revision: https://reviews.llvm.org/D27279
llvm-svn: 289225
2016-12-10 01:14:05 +08:00
|
|
|
ArrayRef<NamedDecl*>
|
|
|
|
DeclsInPrototype,
|
2011-03-12 19:17:06 +08:00
|
|
|
SourceLocation LocalRangeBegin,
|
|
|
|
SourceLocation LocalRangeEnd,
|
2010-10-02 02:44:50 +08:00
|
|
|
Declarator &TheDeclarator,
|
2019-01-09 19:25:09 +08:00
|
|
|
TypeResult TrailingReturnType,
|
|
|
|
DeclSpec *MethodQualifiers) {
|
|
|
|
assert(!(MethodQualifiers && MethodQualifiers->getTypeQualifiers() & DeclSpec::TQ_atomic) &&
|
2013-03-28 09:55:44 +08:00
|
|
|
"function cannot have _Atomic qualifier");
|
|
|
|
|
2009-01-21 03:11:22 +08:00
|
|
|
DeclaratorChunk I;
|
2011-03-06 06:42:13 +08:00
|
|
|
I.Kind = Function;
|
2011-03-12 19:17:06 +08:00
|
|
|
I.Loc = LocalRangeBegin;
|
|
|
|
I.EndLoc = LocalRangeEnd;
|
2011-03-06 06:42:13 +08:00
|
|
|
I.Fun.hasPrototype = hasProto;
|
2012-10-05 05:42:10 +08:00
|
|
|
I.Fun.isVariadic = EllipsisLoc.isValid();
|
2012-07-31 05:30:52 +08:00
|
|
|
I.Fun.isAmbiguous = isAmbiguous;
|
2012-10-05 05:42:10 +08:00
|
|
|
I.Fun.LParenLoc = LParenLoc.getRawEncoding();
|
2011-03-06 06:42:13 +08:00
|
|
|
I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding();
|
2012-10-05 05:42:10 +08:00
|
|
|
I.Fun.RParenLoc = RParenLoc.getRawEncoding();
|
2014-02-27 06:27:52 +08:00
|
|
|
I.Fun.DeleteParams = false;
|
|
|
|
I.Fun.NumParams = NumParams;
|
2014-06-09 10:04:02 +08:00
|
|
|
I.Fun.Params = nullptr;
|
2011-01-26 11:43:54 +08:00
|
|
|
I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef;
|
2011-03-06 06:42:13 +08:00
|
|
|
I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding();
|
2011-07-14 05:47:47 +08:00
|
|
|
I.Fun.MutableLoc = MutableLoc.getRawEncoding();
|
2011-03-06 06:42:13 +08:00
|
|
|
I.Fun.ExceptionSpecType = ESpecType;
|
2015-08-26 12:19:36 +08:00
|
|
|
I.Fun.ExceptionSpecLocBeg = ESpecRange.getBegin().getRawEncoding();
|
|
|
|
I.Fun.ExceptionSpecLocEnd = ESpecRange.getEnd().getRawEncoding();
|
Store decls in prototypes on the declarator instead of in the AST
This saves two pointers from FunctionDecl that were being used for some
rare and questionable C-only functionality. The DeclsInPrototypeScope
ArrayRef was added in r151712 in order to parse this kind of C code:
enum e {x, y};
int f(enum {y, x} n) {
return x; // should return 1, not 0
}
The challenge is that we parse 'int f(enum {y, x} n)' it its own
function prototype scope that gets popped before we build the
FunctionDecl for 'f'. The original change was doing two questionable
things:
1. Saving all tag decls introduced in prototype scope on a TU-global
Sema variable. This is problematic when you have cases like this, where
'x' and 'y' shouldn't be visible in 'f':
void f(void (*fp)(enum { x, y } e)) { /* no x */ }
This patch fixes that, so now 'f' can't see 'x', which is consistent
with GCC.
2. Storing the decls in FunctionDecl in ActOnFunctionDeclarator so that
they could be used in ActOnStartOfFunctionDef. This is just an
inefficient way to move information around. The AST lives forever, but
the list of non-parameter decls in prototype scope is short lived.
Moving these things to the Declarator solves both of these issues.
Reviewers: rsmith
Subscribers: jmolloy, cfe-commits
Differential Revision: https://reviews.llvm.org/D27279
llvm-svn: 289225
2016-12-10 01:14:05 +08:00
|
|
|
I.Fun.NumExceptionsOrDecls = 0;
|
2014-06-09 10:04:02 +08:00
|
|
|
I.Fun.Exceptions = nullptr;
|
|
|
|
I.Fun.NoexceptExpr = nullptr;
|
2012-06-12 09:51:59 +08:00
|
|
|
I.Fun.HasTrailingReturnType = TrailingReturnType.isUsable() ||
|
|
|
|
TrailingReturnType.isInvalid();
|
|
|
|
I.Fun.TrailingReturnType = TrailingReturnType.get();
|
2019-01-09 19:25:09 +08:00
|
|
|
I.Fun.MethodQualifiers = nullptr;
|
|
|
|
I.Fun.QualAttrFactory = nullptr;
|
|
|
|
|
|
|
|
if (MethodQualifiers && (MethodQualifiers->getTypeQualifiers() ||
|
|
|
|
MethodQualifiers->getAttributes().size())) {
|
|
|
|
auto &attrs = MethodQualifiers->getAttributes();
|
|
|
|
I.Fun.MethodQualifiers = new DeclSpec(attrs.getPool().getFactory());
|
|
|
|
MethodQualifiers->forEachCVRUQualifier(
|
|
|
|
[&](DeclSpec::TQ TypeQual, StringRef PrintName, SourceLocation SL) {
|
|
|
|
I.Fun.MethodQualifiers->SetTypeQual(TypeQual, SL);
|
|
|
|
});
|
|
|
|
I.Fun.MethodQualifiers->getAttributes().takeAllFrom(attrs);
|
|
|
|
I.Fun.MethodQualifiers->getAttributePool().takeAllFrom(attrs.getPool());
|
|
|
|
}
|
2009-04-30 01:30:04 +08:00
|
|
|
|
2014-11-14 04:01:57 +08:00
|
|
|
assert(I.Fun.ExceptionSpecType == ESpecType && "bitfield overflow");
|
|
|
|
|
2014-02-27 06:27:52 +08:00
|
|
|
// new[] a parameter array if needed.
|
|
|
|
if (NumParams) {
|
2009-01-21 03:11:22 +08:00
|
|
|
// If the 'InlineParams' in Declarator is unused and big enough, put our
|
|
|
|
// parameter list there (in an effort to avoid new/delete traffic). If it
|
|
|
|
// is already used (consider a function returning a function pointer) or too
|
2014-02-27 06:27:52 +08:00
|
|
|
// small (function with too many parameters), go to the heap.
|
2016-07-23 07:36:59 +08:00
|
|
|
if (!TheDeclarator.InlineStorageUsed &&
|
2014-02-27 06:27:52 +08:00
|
|
|
NumParams <= llvm::array_lengthof(TheDeclarator.InlineParams)) {
|
|
|
|
I.Fun.Params = TheDeclarator.InlineParams;
|
2016-11-18 05:00:09 +08:00
|
|
|
new (I.Fun.Params) ParamInfo[NumParams];
|
2014-02-27 06:27:52 +08:00
|
|
|
I.Fun.DeleteParams = false;
|
2016-07-23 07:36:59 +08:00
|
|
|
TheDeclarator.InlineStorageUsed = true;
|
2009-01-21 03:11:22 +08:00
|
|
|
} else {
|
2016-11-18 05:00:09 +08:00
|
|
|
I.Fun.Params = new DeclaratorChunk::ParamInfo[NumParams];
|
2014-02-27 06:27:52 +08:00
|
|
|
I.Fun.DeleteParams = true;
|
2009-01-21 03:11:22 +08:00
|
|
|
}
|
2016-11-18 01:52:58 +08:00
|
|
|
for (unsigned i = 0; i < NumParams; i++)
|
2018-07-31 03:24:48 +08:00
|
|
|
I.Fun.Params[i] = std::move(Params[i]);
|
2009-01-21 03:11:22 +08:00
|
|
|
}
|
2011-03-06 06:42:13 +08:00
|
|
|
|
|
|
|
// Check what exception specification information we should actually store.
|
|
|
|
switch (ESpecType) {
|
|
|
|
default: break; // By default, save nothing.
|
|
|
|
case EST_Dynamic:
|
|
|
|
// new[] an exception array if needed
|
|
|
|
if (NumExceptions) {
|
Store decls in prototypes on the declarator instead of in the AST
This saves two pointers from FunctionDecl that were being used for some
rare and questionable C-only functionality. The DeclsInPrototypeScope
ArrayRef was added in r151712 in order to parse this kind of C code:
enum e {x, y};
int f(enum {y, x} n) {
return x; // should return 1, not 0
}
The challenge is that we parse 'int f(enum {y, x} n)' it its own
function prototype scope that gets popped before we build the
FunctionDecl for 'f'. The original change was doing two questionable
things:
1. Saving all tag decls introduced in prototype scope on a TU-global
Sema variable. This is problematic when you have cases like this, where
'x' and 'y' shouldn't be visible in 'f':
void f(void (*fp)(enum { x, y } e)) { /* no x */ }
This patch fixes that, so now 'f' can't see 'x', which is consistent
with GCC.
2. Storing the decls in FunctionDecl in ActOnFunctionDeclarator so that
they could be used in ActOnStartOfFunctionDef. This is just an
inefficient way to move information around. The AST lives forever, but
the list of non-parameter decls in prototype scope is short lived.
Moving these things to the Declarator solves both of these issues.
Reviewers: rsmith
Subscribers: jmolloy, cfe-commits
Differential Revision: https://reviews.llvm.org/D27279
llvm-svn: 289225
2016-12-10 01:14:05 +08:00
|
|
|
I.Fun.NumExceptionsOrDecls = NumExceptions;
|
2011-03-06 06:42:13 +08:00
|
|
|
I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions];
|
|
|
|
for (unsigned i = 0; i != NumExceptions; ++i) {
|
|
|
|
I.Fun.Exceptions[i].Ty = Exceptions[i];
|
|
|
|
I.Fun.Exceptions[i].Range = ExceptionRanges[i];
|
|
|
|
}
|
2009-05-30 02:02:33 +08:00
|
|
|
}
|
2011-03-06 06:42:13 +08:00
|
|
|
break;
|
|
|
|
|
2018-05-03 11:58:32 +08:00
|
|
|
case EST_DependentNoexcept:
|
|
|
|
case EST_NoexceptFalse:
|
|
|
|
case EST_NoexceptTrue:
|
2011-03-06 06:42:13 +08:00
|
|
|
I.Fun.NoexceptExpr = NoexceptExpr;
|
|
|
|
break;
|
2014-11-14 04:01:57 +08:00
|
|
|
|
|
|
|
case EST_Unparsed:
|
|
|
|
I.Fun.ExceptionSpecTokens = ExceptionSpecTokens;
|
|
|
|
break;
|
2009-04-30 01:30:04 +08:00
|
|
|
}
|
Store decls in prototypes on the declarator instead of in the AST
This saves two pointers from FunctionDecl that were being used for some
rare and questionable C-only functionality. The DeclsInPrototypeScope
ArrayRef was added in r151712 in order to parse this kind of C code:
enum e {x, y};
int f(enum {y, x} n) {
return x; // should return 1, not 0
}
The challenge is that we parse 'int f(enum {y, x} n)' it its own
function prototype scope that gets popped before we build the
FunctionDecl for 'f'. The original change was doing two questionable
things:
1. Saving all tag decls introduced in prototype scope on a TU-global
Sema variable. This is problematic when you have cases like this, where
'x' and 'y' shouldn't be visible in 'f':
void f(void (*fp)(enum { x, y } e)) { /* no x */ }
This patch fixes that, so now 'f' can't see 'x', which is consistent
with GCC.
2. Storing the decls in FunctionDecl in ActOnFunctionDeclarator so that
they could be used in ActOnStartOfFunctionDef. This is just an
inefficient way to move information around. The AST lives forever, but
the list of non-parameter decls in prototype scope is short lived.
Moving these things to the Declarator solves both of these issues.
Reviewers: rsmith
Subscribers: jmolloy, cfe-commits
Differential Revision: https://reviews.llvm.org/D27279
llvm-svn: 289225
2016-12-10 01:14:05 +08:00
|
|
|
|
|
|
|
if (!DeclsInPrototype.empty()) {
|
|
|
|
assert(ESpecType == EST_None && NumExceptions == 0 &&
|
|
|
|
"cannot have exception specifiers and decls in prototype");
|
|
|
|
I.Fun.NumExceptionsOrDecls = DeclsInPrototype.size();
|
|
|
|
// Copy the array of decls into stable heap storage.
|
|
|
|
I.Fun.DeclsInPrototype = new NamedDecl *[DeclsInPrototype.size()];
|
|
|
|
for (size_t J = 0; J < DeclsInPrototype.size(); ++J)
|
|
|
|
I.Fun.DeclsInPrototype[J] = DeclsInPrototype[J];
|
|
|
|
}
|
|
|
|
|
2009-01-21 03:11:22 +08:00
|
|
|
return I;
|
|
|
|
}
|
2008-11-22 16:32:36 +08:00
|
|
|
|
2016-07-23 07:36:59 +08:00
|
|
|
void Declarator::setDecompositionBindings(
|
|
|
|
SourceLocation LSquareLoc,
|
|
|
|
ArrayRef<DecompositionDeclarator::Binding> Bindings,
|
|
|
|
SourceLocation RSquareLoc) {
|
|
|
|
assert(!hasName() && "declarator given multiple names!");
|
|
|
|
|
|
|
|
BindingGroup.LSquareLoc = LSquareLoc;
|
|
|
|
BindingGroup.RSquareLoc = RSquareLoc;
|
|
|
|
BindingGroup.NumBindings = Bindings.size();
|
|
|
|
Range.setEnd(RSquareLoc);
|
|
|
|
|
|
|
|
// We're now past the identifier.
|
|
|
|
SetIdentifier(nullptr, LSquareLoc);
|
|
|
|
Name.EndLocation = RSquareLoc;
|
|
|
|
|
|
|
|
// Allocate storage for bindings and stash them away.
|
2018-04-06 06:15:42 +08:00
|
|
|
if (Bindings.size()) {
|
2016-07-23 07:36:59 +08:00
|
|
|
if (!InlineStorageUsed &&
|
|
|
|
Bindings.size() <= llvm::array_lengthof(InlineBindings)) {
|
|
|
|
BindingGroup.Bindings = InlineBindings;
|
|
|
|
BindingGroup.DeleteBindings = false;
|
|
|
|
InlineStorageUsed = true;
|
|
|
|
} else {
|
|
|
|
BindingGroup.Bindings =
|
|
|
|
new DecompositionDeclarator::Binding[Bindings.size()];
|
|
|
|
BindingGroup.DeleteBindings = true;
|
|
|
|
}
|
|
|
|
std::uninitialized_copy(Bindings.begin(), Bindings.end(),
|
|
|
|
BindingGroup.Bindings);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-25 08:56:27 +08:00
|
|
|
bool Declarator::isDeclarationOfFunction() const {
|
2018-04-06 06:15:42 +08:00
|
|
|
for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) {
|
|
|
|
switch (DeclTypeInfo[i].Kind) {
|
2011-06-25 10:28:38 +08:00
|
|
|
case DeclaratorChunk::Function:
|
|
|
|
return true;
|
|
|
|
case DeclaratorChunk::Paren:
|
|
|
|
continue;
|
|
|
|
case DeclaratorChunk::Pointer:
|
|
|
|
case DeclaratorChunk::Reference:
|
|
|
|
case DeclaratorChunk::Array:
|
|
|
|
case DeclaratorChunk::BlockPointer:
|
|
|
|
case DeclaratorChunk::MemberPointer:
|
2016-01-09 20:53:17 +08:00
|
|
|
case DeclaratorChunk::Pipe:
|
2011-06-25 10:28:38 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
llvm_unreachable("Invalid type chunk");
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-06-25 08:56:27 +08:00
|
|
|
switch (DS.getTypeSpecType()) {
|
2018-01-02 02:23:28 +08:00
|
|
|
case TST_atomic:
|
|
|
|
case TST_auto:
|
|
|
|
case TST_auto_type:
|
|
|
|
case TST_bool:
|
|
|
|
case TST_char:
|
2018-05-01 13:02:45 +08:00
|
|
|
case TST_char8:
|
2018-01-02 02:23:28 +08:00
|
|
|
case TST_char16:
|
|
|
|
case TST_char32:
|
|
|
|
case TST_class:
|
|
|
|
case TST_decimal128:
|
|
|
|
case TST_decimal32:
|
|
|
|
case TST_decimal64:
|
|
|
|
case TST_double:
|
2018-06-05 00:07:52 +08:00
|
|
|
case TST_Accum:
|
2018-06-14 22:53:51 +08:00
|
|
|
case TST_Fract:
|
2018-01-02 02:23:28 +08:00
|
|
|
case TST_Float16:
|
|
|
|
case TST_float128:
|
|
|
|
case TST_enum:
|
|
|
|
case TST_error:
|
|
|
|
case TST_float:
|
|
|
|
case TST_half:
|
|
|
|
case TST_int:
|
|
|
|
case TST_int128:
|
|
|
|
case TST_struct:
|
|
|
|
case TST_interface:
|
|
|
|
case TST_union:
|
|
|
|
case TST_unknown_anytype:
|
|
|
|
case TST_unspecified:
|
|
|
|
case TST_void:
|
|
|
|
case TST_wchar:
|
|
|
|
#define GENERIC_IMAGE_TYPE(ImgType, Id) case TST_##ImgType##_t:
|
2016-04-13 16:33:41 +08:00
|
|
|
#include "clang/Basic/OpenCLImageTypes.def"
|
2011-06-25 08:56:27 +08:00
|
|
|
return false;
|
|
|
|
|
2018-01-02 02:23:28 +08:00
|
|
|
case TST_decltype_auto:
|
2013-04-27 00:15:35 +08:00
|
|
|
// This must have an initializer, so can't be a function declaration,
|
|
|
|
// even if the initializer has function type.
|
|
|
|
return false;
|
|
|
|
|
2018-01-02 02:23:28 +08:00
|
|
|
case TST_decltype:
|
|
|
|
case TST_typeofExpr:
|
2011-06-25 08:56:27 +08:00
|
|
|
if (Expr *E = DS.getRepAsExpr())
|
|
|
|
return E->getType()->isFunctionType();
|
|
|
|
return false;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2018-01-02 02:23:28 +08:00
|
|
|
case TST_underlyingType:
|
|
|
|
case TST_typename:
|
|
|
|
case TST_typeofType: {
|
2011-06-25 08:56:27 +08:00
|
|
|
QualType QT = DS.getRepAsType().get();
|
|
|
|
if (QT.isNull())
|
|
|
|
return false;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2018-04-06 06:15:42 +08:00
|
|
|
if (const LocInfoType *LIT = dyn_cast<LocInfoType>(QT))
|
2011-06-25 08:56:27 +08:00
|
|
|
QT = LIT->getType();
|
|
|
|
|
|
|
|
if (QT.isNull())
|
|
|
|
return false;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-06-25 08:56:27 +08:00
|
|
|
return QT->isFunctionType();
|
|
|
|
}
|
|
|
|
}
|
2012-01-17 14:56:22 +08:00
|
|
|
|
|
|
|
llvm_unreachable("Invalid TypeSpecType!");
|
2011-06-25 08:56:27 +08:00
|
|
|
}
|
|
|
|
|
2013-10-08 08:58:57 +08:00
|
|
|
bool Declarator::isStaticMember() {
|
2017-12-29 13:41:00 +08:00
|
|
|
assert(getContext() == DeclaratorContext::MemberContext);
|
2013-10-08 08:58:57 +08:00
|
|
|
return getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
|
2017-12-30 12:15:27 +08:00
|
|
|
(getName().Kind == UnqualifiedIdKind::IK_OperatorFunctionId &&
|
2015-03-30 08:43:56 +08:00
|
|
|
CXXMethodDecl::isStaticOverloadedOperator(
|
|
|
|
getName().OperatorFunctionId.Operator));
|
2013-10-08 08:58:57 +08:00
|
|
|
}
|
|
|
|
|
2015-09-15 05:29:57 +08:00
|
|
|
bool Declarator::isCtorOrDtor() {
|
2017-12-30 12:15:27 +08:00
|
|
|
return (getName().getKind() == UnqualifiedIdKind::IK_ConstructorName) ||
|
|
|
|
(getName().getKind() == UnqualifiedIdKind::IK_DestructorName);
|
2015-09-15 05:29:57 +08:00
|
|
|
}
|
|
|
|
|
2019-01-09 19:25:09 +08:00
|
|
|
void DeclSpec::forEachCVRUQualifier(
|
|
|
|
llvm::function_ref<void(TQ, StringRef, SourceLocation)> Handle) {
|
|
|
|
if (TypeQualifiers & TQ_const)
|
|
|
|
Handle(TQ_const, "const", TQ_constLoc);
|
|
|
|
if (TypeQualifiers & TQ_volatile)
|
|
|
|
Handle(TQ_volatile, "volatile", TQ_volatileLoc);
|
|
|
|
if (TypeQualifiers & TQ_restrict)
|
|
|
|
Handle(TQ_restrict, "restrict", TQ_restrictLoc);
|
|
|
|
if (TypeQualifiers & TQ_unaligned)
|
|
|
|
Handle(TQ_unaligned, "unaligned", TQ_unalignedLoc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeclSpec::forEachQualifier(
|
|
|
|
llvm::function_ref<void(TQ, StringRef, SourceLocation)> Handle) {
|
|
|
|
forEachCVRUQualifier(Handle);
|
|
|
|
// FIXME: Add code below to iterate through the attributes and call Handle.
|
|
|
|
}
|
|
|
|
|
2013-11-20 06:47:36 +08:00
|
|
|
bool DeclSpec::hasTagDefinition() const {
|
|
|
|
if (!TypeSpecOwned)
|
|
|
|
return false;
|
|
|
|
return cast<TagDecl>(getRepAsDecl())->isCompleteDefinition();
|
|
|
|
}
|
|
|
|
|
2006-08-04 12:39:53 +08:00
|
|
|
/// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
|
2009-02-28 02:35:46 +08:00
|
|
|
/// declaration specifier includes.
|
2018-04-06 06:15:42 +08:00
|
|
|
///
|
2006-08-04 12:39:53 +08:00
|
|
|
unsigned DeclSpec::getParsedSpecifiers() const {
|
|
|
|
unsigned Res = 0;
|
2006-08-05 11:28:50 +08:00
|
|
|
if (StorageClassSpec != SCS_unspecified ||
|
2013-04-13 06:46:28 +08:00
|
|
|
ThreadStorageClassSpec != TSCS_unspecified)
|
2006-08-04 12:39:53 +08:00
|
|
|
Res |= PQ_StorageClassSpecifier;
|
2008-06-20 03:52:46 +08:00
|
|
|
|
2006-11-28 13:05:08 +08:00
|
|
|
if (TypeQualifiers != TQ_unspecified)
|
2006-08-04 12:39:53 +08:00
|
|
|
Res |= PQ_TypeQualifier;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2006-11-28 12:28:12 +08:00
|
|
|
if (hasTypeSpecifier())
|
2006-08-04 12:39:53 +08:00
|
|
|
Res |= PQ_TypeSpecifier;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2019-05-09 11:59:21 +08:00
|
|
|
if (FS_inline_specified || FS_virtual_specified || hasExplicitSpecifier() ||
|
2013-11-13 14:57:53 +08:00
|
|
|
FS_noreturn_specified || FS_forceinline_specified)
|
2006-08-04 12:39:53 +08:00
|
|
|
Res |= PQ_FunctionSpecifier;
|
|
|
|
return Res;
|
|
|
|
}
|
|
|
|
|
2009-08-04 04:12:06 +08:00
|
|
|
template <class T> static bool BadSpecifier(T TNew, T TPrev,
|
|
|
|
const char *&PrevSpec,
|
2012-08-29 04:55:40 +08:00
|
|
|
unsigned &DiagID,
|
|
|
|
bool IsExtension = true) {
|
2009-08-04 02:47:27 +08:00
|
|
|
PrevSpec = DeclSpec::getSpecifierName(TPrev);
|
2012-08-29 04:55:40 +08:00
|
|
|
if (TNew != TPrev)
|
|
|
|
DiagID = diag::err_invalid_decl_spec_combination;
|
|
|
|
else
|
2018-10-04 07:09:29 +08:00
|
|
|
DiagID = IsExtension ? diag::ext_warn_duplicate_declspec :
|
2018-07-31 03:24:48 +08:00
|
|
|
diag::warn_duplicate_declspec;
|
2009-08-04 02:47:27 +08:00
|
|
|
return true;
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-08-04 02:47:27 +08:00
|
|
|
|
2007-01-23 12:35:33 +08:00
|
|
|
const char *DeclSpec::getSpecifierName(DeclSpec::SCS S) {
|
2006-08-05 11:28:50 +08:00
|
|
|
switch (S) {
|
|
|
|
case DeclSpec::SCS_unspecified: return "unspecified";
|
|
|
|
case DeclSpec::SCS_typedef: return "typedef";
|
|
|
|
case DeclSpec::SCS_extern: return "extern";
|
|
|
|
case DeclSpec::SCS_static: return "static";
|
|
|
|
case DeclSpec::SCS_auto: return "auto";
|
|
|
|
case DeclSpec::SCS_register: return "register";
|
2009-04-20 04:27:55 +08:00
|
|
|
case DeclSpec::SCS_private_extern: return "__private_extern__";
|
2008-11-15 07:42:31 +08:00
|
|
|
case DeclSpec::SCS_mutable: return "mutable";
|
2006-08-05 11:28:50 +08:00
|
|
|
}
|
2009-12-12 13:05:38 +08:00
|
|
|
llvm_unreachable("Unknown typespec!");
|
2006-08-05 11:28:50 +08:00
|
|
|
}
|
|
|
|
|
2013-04-13 06:46:28 +08:00
|
|
|
const char *DeclSpec::getSpecifierName(DeclSpec::TSCS S) {
|
|
|
|
switch (S) {
|
|
|
|
case DeclSpec::TSCS_unspecified: return "unspecified";
|
|
|
|
case DeclSpec::TSCS___thread: return "__thread";
|
|
|
|
case DeclSpec::TSCS_thread_local: return "thread_local";
|
|
|
|
case DeclSpec::TSCS__Thread_local: return "_Thread_local";
|
|
|
|
}
|
|
|
|
llvm_unreachable("Unknown typespec!");
|
|
|
|
}
|
|
|
|
|
2009-08-04 02:47:27 +08:00
|
|
|
const char *DeclSpec::getSpecifierName(TSW W) {
|
2006-08-04 12:39:53 +08:00
|
|
|
switch (W) {
|
2009-08-04 02:47:27 +08:00
|
|
|
case TSW_unspecified: return "unspecified";
|
|
|
|
case TSW_short: return "short";
|
|
|
|
case TSW_long: return "long";
|
|
|
|
case TSW_longlong: return "long long";
|
2006-08-04 12:39:53 +08:00
|
|
|
}
|
2009-12-12 13:05:38 +08:00
|
|
|
llvm_unreachable("Unknown typespec!");
|
2006-08-04 12:39:53 +08:00
|
|
|
}
|
|
|
|
|
2009-08-04 02:47:27 +08:00
|
|
|
const char *DeclSpec::getSpecifierName(TSC C) {
|
2006-08-04 12:39:53 +08:00
|
|
|
switch (C) {
|
2009-08-04 02:47:27 +08:00
|
|
|
case TSC_unspecified: return "unspecified";
|
|
|
|
case TSC_imaginary: return "imaginary";
|
|
|
|
case TSC_complex: return "complex";
|
2006-08-04 12:39:53 +08:00
|
|
|
}
|
2009-12-12 13:05:38 +08:00
|
|
|
llvm_unreachable("Unknown typespec!");
|
2006-08-04 12:39:53 +08:00
|
|
|
}
|
|
|
|
|
2018-04-06 06:15:42 +08:00
|
|
|
|
2009-08-04 02:47:27 +08:00
|
|
|
const char *DeclSpec::getSpecifierName(TSS S) {
|
2006-08-04 12:39:53 +08:00
|
|
|
switch (S) {
|
2009-08-04 02:47:27 +08:00
|
|
|
case TSS_unspecified: return "unspecified";
|
|
|
|
case TSS_signed: return "signed";
|
|
|
|
case TSS_unsigned: return "unsigned";
|
2006-08-04 12:39:53 +08:00
|
|
|
}
|
2009-12-12 13:05:38 +08:00
|
|
|
llvm_unreachable("Unknown typespec!");
|
2006-08-04 12:39:53 +08:00
|
|
|
}
|
2018-04-26 08:42:40 +08:00
|
|
|
|
2014-01-15 17:15:43 +08:00
|
|
|
const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
|
|
|
|
const PrintingPolicy &Policy) {
|
2006-08-04 12:39:53 +08:00
|
|
|
switch (T) {
|
2006-08-04 14:15:52 +08:00
|
|
|
case DeclSpec::TST_unspecified: return "unspecified";
|
|
|
|
case DeclSpec::TST_void: return "void";
|
|
|
|
case DeclSpec::TST_char: return "char";
|
2018-01-02 02:23:28 +08:00
|
|
|
case DeclSpec::TST_wchar: return Policy.MSWChar ? "__wchar_t" : "wchar_t";
|
2018-05-01 13:02:45 +08:00
|
|
|
case DeclSpec::TST_char8: return "char8_t";
|
2009-07-14 14:30:34 +08:00
|
|
|
case DeclSpec::TST_char16: return "char16_t";
|
|
|
|
case DeclSpec::TST_char32: return "char32_t";
|
2006-08-04 14:15:52 +08:00
|
|
|
case DeclSpec::TST_int: return "int";
|
2012-04-04 14:24:32 +08:00
|
|
|
case DeclSpec::TST_int128: return "__int128";
|
2011-10-15 07:23:15 +08:00
|
|
|
case DeclSpec::TST_half: return "half";
|
2006-08-04 14:15:52 +08:00
|
|
|
case DeclSpec::TST_float: return "float";
|
|
|
|
case DeclSpec::TST_double: return "double";
|
2018-06-05 00:07:52 +08:00
|
|
|
case DeclSpec::TST_accum: return "_Accum";
|
2018-06-14 22:53:51 +08:00
|
|
|
case DeclSpec::TST_fract: return "_Fract";
|
2017-09-08 23:15:00 +08:00
|
|
|
case DeclSpec::TST_float16: return "_Float16";
|
2016-05-09 16:52:33 +08:00
|
|
|
case DeclSpec::TST_float128: return "__float128";
|
2014-01-15 17:15:43 +08:00
|
|
|
case DeclSpec::TST_bool: return Policy.Bool ? "bool" : "_Bool";
|
2006-08-04 14:15:52 +08:00
|
|
|
case DeclSpec::TST_decimal32: return "_Decimal32";
|
|
|
|
case DeclSpec::TST_decimal64: return "_Decimal64";
|
|
|
|
case DeclSpec::TST_decimal128: return "_Decimal128";
|
2006-08-14 06:16:42 +08:00
|
|
|
case DeclSpec::TST_enum: return "enum";
|
2008-04-14 02:59:07 +08:00
|
|
|
case DeclSpec::TST_class: return "class";
|
2006-08-14 06:16:42 +08:00
|
|
|
case DeclSpec::TST_union: return "union";
|
|
|
|
case DeclSpec::TST_struct: return "struct";
|
2012-09-01 02:45:21 +08:00
|
|
|
case DeclSpec::TST_interface: return "__interface";
|
2009-02-09 23:09:02 +08:00
|
|
|
case DeclSpec::TST_typename: return "type-name";
|
2007-07-31 20:34:36 +08:00
|
|
|
case DeclSpec::TST_typeofType:
|
|
|
|
case DeclSpec::TST_typeofExpr: return "typeof";
|
2009-08-04 02:47:27 +08:00
|
|
|
case DeclSpec::TST_auto: return "auto";
|
2015-11-11 10:02:15 +08:00
|
|
|
case DeclSpec::TST_auto_type: return "__auto_type";
|
2009-08-04 02:47:27 +08:00
|
|
|
case DeclSpec::TST_decltype: return "(decltype)";
|
2013-04-27 00:15:35 +08:00
|
|
|
case DeclSpec::TST_decltype_auto: return "decltype(auto)";
|
2011-05-25 06:41:36 +08:00
|
|
|
case DeclSpec::TST_underlyingType: return "__underlying_type";
|
2011-04-10 06:50:59 +08:00
|
|
|
case DeclSpec::TST_unknown_anytype: return "__unknown_anytype";
|
2011-10-07 07:00:33 +08:00
|
|
|
case DeclSpec::TST_atomic: return "_Atomic";
|
2016-04-08 21:40:33 +08:00
|
|
|
#define GENERIC_IMAGE_TYPE(ImgType, Id) \
|
|
|
|
case DeclSpec::TST_##ImgType##_t: \
|
|
|
|
return #ImgType "_t";
|
2016-04-13 16:33:41 +08:00
|
|
|
#include "clang/Basic/OpenCLImageTypes.def"
|
2009-08-04 02:47:27 +08:00
|
|
|
case DeclSpec::TST_error: return "(error)";
|
2006-08-04 12:39:53 +08:00
|
|
|
}
|
2009-12-12 13:05:38 +08:00
|
|
|
llvm_unreachable("Unknown typespec!");
|
2006-08-04 14:15:52 +08:00
|
|
|
}
|
|
|
|
|
2019-06-14 16:56:20 +08:00
|
|
|
const char *DeclSpec::getSpecifierName(ConstexprSpecKind C) {
|
|
|
|
switch (C) {
|
|
|
|
case CSK_unspecified: return "unspecified";
|
|
|
|
case CSK_constexpr: return "constexpr";
|
|
|
|
case CSK_consteval: return "consteval";
|
|
|
|
}
|
|
|
|
llvm_unreachable("Unknown ConstexprSpecKind");
|
|
|
|
}
|
|
|
|
|
2009-08-04 02:47:27 +08:00
|
|
|
const char *DeclSpec::getSpecifierName(TQ T) {
|
2006-08-04 13:25:55 +08:00
|
|
|
switch (T) {
|
2009-08-04 02:47:27 +08:00
|
|
|
case DeclSpec::TQ_unspecified: return "unspecified";
|
|
|
|
case DeclSpec::TQ_const: return "const";
|
|
|
|
case DeclSpec::TQ_restrict: return "restrict";
|
|
|
|
case DeclSpec::TQ_volatile: return "volatile";
|
2013-03-28 09:55:44 +08:00
|
|
|
case DeclSpec::TQ_atomic: return "_Atomic";
|
2016-05-12 02:38:21 +08:00
|
|
|
case DeclSpec::TQ_unaligned: return "__unaligned";
|
2006-08-04 13:25:55 +08:00
|
|
|
}
|
2009-12-12 13:05:38 +08:00
|
|
|
llvm_unreachable("Unknown typespec!");
|
2006-08-04 13:25:55 +08:00
|
|
|
}
|
2006-08-04 12:39:53 +08:00
|
|
|
|
2011-10-06 11:01:00 +08:00
|
|
|
bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc,
|
2009-08-04 04:12:06 +08:00
|
|
|
const char *&PrevSpec,
|
2014-01-15 17:15:43 +08:00
|
|
|
unsigned &DiagID,
|
|
|
|
const PrintingPolicy &Policy) {
|
2012-06-20 07:09:52 +08:00
|
|
|
// OpenCL v1.1 s6.8g: "The extern, static, auto and register storage-class
|
|
|
|
// specifiers are not supported.
|
2011-02-12 03:59:54 +08:00
|
|
|
// It seems sensible to prohibit private_extern too
|
2011-10-06 11:01:00 +08:00
|
|
|
// The cl_clang_storage_class_specifiers extension enables support for
|
|
|
|
// these storage-class specifiers.
|
2012-06-20 07:09:52 +08:00
|
|
|
// OpenCL v1.2 s6.8 changes this to "The auto and register storage-class
|
|
|
|
// specifiers are not supported."
|
2018-11-17 00:22:56 +08:00
|
|
|
// OpenCL C++ v1.0 s2.9 restricts register.
|
2012-03-11 15:00:24 +08:00
|
|
|
if (S.getLangOpts().OpenCL &&
|
2016-12-18 13:18:55 +08:00
|
|
|
!S.getOpenCLOptions().isEnabled("cl_clang_storage_class_specifiers")) {
|
2011-10-06 11:01:00 +08:00
|
|
|
switch (SC) {
|
2011-02-12 03:59:54 +08:00
|
|
|
case SCS_extern:
|
|
|
|
case SCS_private_extern:
|
2012-06-20 07:09:52 +08:00
|
|
|
case SCS_static:
|
2018-11-17 00:22:56 +08:00
|
|
|
if (S.getLangOpts().OpenCLVersion < 120 &&
|
|
|
|
!S.getLangOpts().OpenCLCPlusPlus) {
|
|
|
|
DiagID = diag::err_opencl_unknown_type_specifier;
|
2015-11-15 03:31:52 +08:00
|
|
|
PrevSpec = getSpecifierName(SC);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
2011-02-12 03:59:54 +08:00
|
|
|
case SCS_auto:
|
|
|
|
case SCS_register:
|
2014-11-26 22:10:06 +08:00
|
|
|
DiagID = diag::err_opencl_unknown_type_specifier;
|
2011-10-06 11:01:00 +08:00
|
|
|
PrevSpec = getSpecifierName(SC);
|
2011-02-12 03:59:54 +08:00
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-31 00:47:02 +08:00
|
|
|
if (StorageClassSpec != SCS_unspecified) {
|
2013-04-27 00:15:35 +08:00
|
|
|
// Maybe this is an attempt to use C++11 'auto' outside of C++11 mode.
|
2011-09-05 03:54:14 +08:00
|
|
|
bool isInvalid = true;
|
2012-03-11 15:00:24 +08:00
|
|
|
if (TypeSpecType == TST_unspecified && S.getLangOpts().CPlusPlus) {
|
2011-10-06 11:01:00 +08:00
|
|
|
if (SC == SCS_auto)
|
2014-01-15 17:15:43 +08:00
|
|
|
return SetTypeSpecType(TST_auto, Loc, PrevSpec, DiagID, Policy);
|
2011-09-05 03:54:14 +08:00
|
|
|
if (StorageClassSpec == SCS_auto) {
|
|
|
|
isInvalid = SetTypeSpecType(TST_auto, StorageClassSpecLoc,
|
2014-01-15 17:15:43 +08:00
|
|
|
PrevSpec, DiagID, Policy);
|
2011-09-05 03:54:14 +08:00
|
|
|
assert(!isInvalid && "auto SCS -> TST recovery failed");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-31 00:47:02 +08:00
|
|
|
// Changing storage class is allowed only if the previous one
|
|
|
|
// was the 'extern' that is part of a linkage specification and
|
|
|
|
// the new storage class is 'typedef'.
|
2011-09-05 03:54:14 +08:00
|
|
|
if (isInvalid &&
|
|
|
|
!(SCS_extern_in_linkage_spec &&
|
2010-07-31 00:47:02 +08:00
|
|
|
StorageClassSpec == SCS_extern &&
|
2011-10-06 11:01:00 +08:00
|
|
|
SC == SCS_typedef))
|
|
|
|
return BadSpecifier(SC, (SCS)StorageClassSpec, PrevSpec, DiagID);
|
2010-07-31 00:47:02 +08:00
|
|
|
}
|
2011-10-06 11:01:00 +08:00
|
|
|
StorageClassSpec = SC;
|
2006-11-28 13:05:08 +08:00
|
|
|
StorageClassSpecLoc = Loc;
|
2011-10-06 11:01:00 +08:00
|
|
|
assert((unsigned)SC == StorageClassSpec && "SCS constants overflow bitfield");
|
2006-08-05 11:28:50 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-04-13 06:46:28 +08:00
|
|
|
bool DeclSpec::SetStorageClassSpecThread(TSCS TSC, SourceLocation Loc,
|
2009-08-04 04:12:06 +08:00
|
|
|
const char *&PrevSpec,
|
|
|
|
unsigned &DiagID) {
|
2013-04-13 06:46:28 +08:00
|
|
|
if (ThreadStorageClassSpec != TSCS_unspecified)
|
|
|
|
return BadSpecifier(TSC, (TSCS)ThreadStorageClassSpec, PrevSpec, DiagID);
|
|
|
|
|
|
|
|
ThreadStorageClassSpec = TSC;
|
|
|
|
ThreadStorageClassSpecLoc = Loc;
|
2006-11-28 12:50:12 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-08-04 12:39:53 +08:00
|
|
|
/// These methods set the specified attribute of the DeclSpec, but return true
|
|
|
|
/// and ignore the request if invalid (e.g. "extern" then "auto" is
|
|
|
|
/// specified).
|
2006-11-28 13:30:29 +08:00
|
|
|
bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc,
|
2009-08-04 04:12:06 +08:00
|
|
|
const char *&PrevSpec,
|
2014-01-15 17:15:43 +08:00
|
|
|
unsigned &DiagID,
|
|
|
|
const PrintingPolicy &Policy) {
|
2016-10-22 05:13:56 +08:00
|
|
|
// Overwrite TSWRange.Begin only if TypeSpecWidth was unspecified, so that
|
2011-03-07 06:21:56 +08:00
|
|
|
// for 'long long' we will keep the source location of the first 'long'.
|
|
|
|
if (TypeSpecWidth == TSW_unspecified)
|
2016-10-22 05:13:56 +08:00
|
|
|
TSWRange.setBegin(Loc);
|
2011-03-07 06:21:56 +08:00
|
|
|
// Allow turning long -> long long.
|
|
|
|
else if (W != TSW_longlong || TypeSpecWidth != TSW_long)
|
2009-08-04 04:12:06 +08:00
|
|
|
return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID);
|
2006-08-04 12:39:53 +08:00
|
|
|
TypeSpecWidth = W;
|
2016-10-22 05:13:56 +08:00
|
|
|
// Remember location of the last 'long'
|
|
|
|
TSWRange.setEnd(Loc);
|
2006-08-04 12:39:53 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
bool DeclSpec::SetTypeSpecComplex(TSC C, SourceLocation Loc,
|
2009-08-04 04:12:06 +08:00
|
|
|
const char *&PrevSpec,
|
|
|
|
unsigned &DiagID) {
|
2006-08-04 12:39:53 +08:00
|
|
|
if (TypeSpecComplex != TSC_unspecified)
|
2009-08-04 04:12:06 +08:00
|
|
|
return BadSpecifier(C, (TSC)TypeSpecComplex, PrevSpec, DiagID);
|
2006-08-04 12:39:53 +08:00
|
|
|
TypeSpecComplex = C;
|
2006-11-28 13:30:29 +08:00
|
|
|
TSCLoc = Loc;
|
2006-08-04 12:39:53 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
bool DeclSpec::SetTypeSpecSign(TSS S, SourceLocation Loc,
|
2009-08-04 04:12:06 +08:00
|
|
|
const char *&PrevSpec,
|
|
|
|
unsigned &DiagID) {
|
2006-08-04 12:39:53 +08:00
|
|
|
if (TypeSpecSign != TSS_unspecified)
|
2009-08-04 04:12:06 +08:00
|
|
|
return BadSpecifier(S, (TSS)TypeSpecSign, PrevSpec, DiagID);
|
2006-08-04 13:26:52 +08:00
|
|
|
TypeSpecSign = S;
|
2006-11-28 13:30:29 +08:00
|
|
|
TSSLoc = Loc;
|
2006-08-04 12:39:53 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-11-28 13:30:29 +08:00
|
|
|
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
|
2009-08-04 04:12:06 +08:00
|
|
|
const char *&PrevSpec,
|
|
|
|
unsigned &DiagID,
|
2014-01-15 17:15:43 +08:00
|
|
|
ParsedType Rep,
|
|
|
|
const PrintingPolicy &Policy) {
|
|
|
|
return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep, Policy);
|
2011-03-17 04:16:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc,
|
|
|
|
SourceLocation TagNameLoc,
|
|
|
|
const char *&PrevSpec,
|
|
|
|
unsigned &DiagID,
|
2014-01-15 17:15:43 +08:00
|
|
|
ParsedType Rep,
|
|
|
|
const PrintingPolicy &Policy) {
|
2010-08-24 13:47:05 +08:00
|
|
|
assert(isTypeRep(T) && "T does not store a type");
|
|
|
|
assert(Rep && "no type provided!");
|
2019-05-07 15:36:07 +08:00
|
|
|
if (TypeSpecType == TST_error)
|
|
|
|
return false;
|
2010-08-24 13:47:05 +08:00
|
|
|
if (TypeSpecType != TST_unspecified) {
|
2014-01-15 17:15:43 +08:00
|
|
|
PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
|
2010-08-24 13:47:05 +08:00
|
|
|
DiagID = diag::err_invalid_decl_spec_combination;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
TypeSpecType = T;
|
|
|
|
TypeRep = Rep;
|
2011-03-17 04:16:18 +08:00
|
|
|
TSTLoc = TagKwLoc;
|
|
|
|
TSTNameLoc = TagNameLoc;
|
2010-08-24 13:47:05 +08:00
|
|
|
TypeSpecOwned = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
|
|
|
|
const char *&PrevSpec,
|
|
|
|
unsigned &DiagID,
|
2014-01-15 17:15:43 +08:00
|
|
|
Expr *Rep,
|
|
|
|
const PrintingPolicy &Policy) {
|
2010-08-24 13:47:05 +08:00
|
|
|
assert(isExprRep(T) && "T does not store an expr");
|
|
|
|
assert(Rep && "no expression provided!");
|
2019-05-07 15:36:07 +08:00
|
|
|
if (TypeSpecType == TST_error)
|
|
|
|
return false;
|
2010-08-24 13:47:05 +08:00
|
|
|
if (TypeSpecType != TST_unspecified) {
|
2014-01-15 17:15:43 +08:00
|
|
|
PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
|
2010-08-24 13:47:05 +08:00
|
|
|
DiagID = diag::err_invalid_decl_spec_combination;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
TypeSpecType = T;
|
|
|
|
ExprRep = Rep;
|
|
|
|
TSTLoc = Loc;
|
2011-03-17 04:16:18 +08:00
|
|
|
TSTNameLoc = Loc;
|
2010-08-24 13:47:05 +08:00
|
|
|
TypeSpecOwned = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
|
|
|
|
const char *&PrevSpec,
|
|
|
|
unsigned &DiagID,
|
2014-01-15 17:15:43 +08:00
|
|
|
Decl *Rep, bool Owned,
|
|
|
|
const PrintingPolicy &Policy) {
|
|
|
|
return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep, Owned, Policy);
|
2011-03-17 04:16:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc,
|
|
|
|
SourceLocation TagNameLoc,
|
|
|
|
const char *&PrevSpec,
|
|
|
|
unsigned &DiagID,
|
2014-01-15 17:15:43 +08:00
|
|
|
Decl *Rep, bool Owned,
|
|
|
|
const PrintingPolicy &Policy) {
|
2010-08-24 13:47:05 +08:00
|
|
|
assert(isDeclRep(T) && "T does not store a decl");
|
|
|
|
// Unlike the other cases, we don't assert that we actually get a decl.
|
|
|
|
|
2019-05-07 15:36:07 +08:00
|
|
|
if (TypeSpecType == TST_error)
|
|
|
|
return false;
|
2010-08-24 13:47:05 +08:00
|
|
|
if (TypeSpecType != TST_unspecified) {
|
2014-01-15 17:15:43 +08:00
|
|
|
PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
|
2010-08-24 13:47:05 +08:00
|
|
|
DiagID = diag::err_invalid_decl_spec_combination;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
TypeSpecType = T;
|
|
|
|
DeclRep = Rep;
|
2011-03-17 04:16:18 +08:00
|
|
|
TSTLoc = TagKwLoc;
|
|
|
|
TSTNameLoc = TagNameLoc;
|
2014-06-09 10:04:02 +08:00
|
|
|
TypeSpecOwned = Owned && Rep != nullptr;
|
2010-08-24 13:47:05 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
|
|
|
|
const char *&PrevSpec,
|
2014-01-15 17:15:43 +08:00
|
|
|
unsigned &DiagID,
|
|
|
|
const PrintingPolicy &Policy) {
|
2010-08-24 13:47:05 +08:00
|
|
|
assert(!isDeclRep(T) && !isTypeRep(T) && !isExprRep(T) &&
|
|
|
|
"rep required for these type-spec kinds!");
|
2019-05-07 15:36:07 +08:00
|
|
|
if (TypeSpecType == TST_error)
|
|
|
|
return false;
|
2009-08-04 04:12:06 +08:00
|
|
|
if (TypeSpecType != TST_unspecified) {
|
2014-01-15 17:15:43 +08:00
|
|
|
PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
|
2009-08-04 04:12:06 +08:00
|
|
|
DiagID = diag::err_invalid_decl_spec_combination;
|
|
|
|
return true;
|
|
|
|
}
|
2011-03-17 04:16:18 +08:00
|
|
|
TSTLoc = Loc;
|
|
|
|
TSTNameLoc = Loc;
|
2010-06-23 14:00:24 +08:00
|
|
|
if (TypeAltiVecVector && (T == TST_bool) && !TypeAltiVecBool) {
|
|
|
|
TypeAltiVecBool = true;
|
|
|
|
return false;
|
|
|
|
}
|
2006-08-04 13:26:52 +08:00
|
|
|
TypeSpecType = T;
|
2010-08-24 13:47:05 +08:00
|
|
|
TypeSpecOwned = false;
|
2010-02-05 08:12:22 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-06-14 22:53:51 +08:00
|
|
|
bool DeclSpec::SetTypeSpecSat(SourceLocation Loc, const char *&PrevSpec,
|
|
|
|
unsigned &DiagID) {
|
|
|
|
// Cannot set twice
|
|
|
|
if (TypeSpecSat) {
|
|
|
|
DiagID = diag::warn_duplicate_declspec;
|
|
|
|
PrevSpec = "_Sat";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
TypeSpecSat = true;
|
|
|
|
TSSatLoc = Loc;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-02-05 08:12:22 +08:00
|
|
|
bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc,
|
2014-01-15 17:15:43 +08:00
|
|
|
const char *&PrevSpec, unsigned &DiagID,
|
|
|
|
const PrintingPolicy &Policy) {
|
2019-05-07 15:36:07 +08:00
|
|
|
if (TypeSpecType == TST_error)
|
|
|
|
return false;
|
2010-02-05 08:12:22 +08:00
|
|
|
if (TypeSpecType != TST_unspecified) {
|
2014-01-15 17:15:43 +08:00
|
|
|
PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
|
2010-02-05 08:12:22 +08:00
|
|
|
DiagID = diag::err_invalid_vector_decl_spec_combination;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
TypeAltiVecVector = isAltiVecVector;
|
|
|
|
AltiVecLoc = Loc;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-01-09 20:53:17 +08:00
|
|
|
bool DeclSpec::SetTypePipe(bool isPipe, SourceLocation Loc,
|
|
|
|
const char *&PrevSpec, unsigned &DiagID,
|
|
|
|
const PrintingPolicy &Policy) {
|
2019-05-07 15:36:07 +08:00
|
|
|
if (TypeSpecType == TST_error)
|
|
|
|
return false;
|
2016-01-09 20:53:17 +08:00
|
|
|
if (TypeSpecType != TST_unspecified) {
|
|
|
|
PrevSpec = DeclSpec::getSpecifierName((TST)TypeSpecType, Policy);
|
|
|
|
DiagID = diag::err_invalid_decl_spec_combination;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-04-06 06:15:42 +08:00
|
|
|
if (isPipe) {
|
2016-01-09 20:53:17 +08:00
|
|
|
TypeSpecPipe = TSP_pipe;
|
2018-04-06 06:15:42 +08:00
|
|
|
}
|
2016-01-09 20:53:17 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-02-05 08:12:22 +08:00
|
|
|
bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
|
2014-01-15 17:15:43 +08:00
|
|
|
const char *&PrevSpec, unsigned &DiagID,
|
|
|
|
const PrintingPolicy &Policy) {
|
2019-05-07 15:36:07 +08:00
|
|
|
if (TypeSpecType == TST_error)
|
|
|
|
return false;
|
2010-06-23 14:00:24 +08:00
|
|
|
if (!TypeAltiVecVector || TypeAltiVecPixel ||
|
|
|
|
(TypeSpecType != TST_unspecified)) {
|
2014-01-15 17:15:43 +08:00
|
|
|
PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
|
2010-02-05 08:12:22 +08:00
|
|
|
DiagID = diag::err_invalid_pixel_decl_spec_combination;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
TypeAltiVecPixel = isAltiVecPixel;
|
|
|
|
TSTLoc = Loc;
|
2011-03-17 04:16:18 +08:00
|
|
|
TSTNameLoc = Loc;
|
2006-08-04 12:39:53 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-07-04 04:54:09 +08:00
|
|
|
bool DeclSpec::SetTypeAltiVecBool(bool isAltiVecBool, SourceLocation Loc,
|
2014-01-15 17:15:43 +08:00
|
|
|
const char *&PrevSpec, unsigned &DiagID,
|
|
|
|
const PrintingPolicy &Policy) {
|
2019-05-07 15:36:07 +08:00
|
|
|
if (TypeSpecType == TST_error)
|
|
|
|
return false;
|
2013-07-04 04:54:09 +08:00
|
|
|
if (!TypeAltiVecVector || TypeAltiVecBool ||
|
|
|
|
(TypeSpecType != TST_unspecified)) {
|
2014-01-15 17:15:43 +08:00
|
|
|
PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType, Policy);
|
2013-07-04 04:54:09 +08:00
|
|
|
DiagID = diag::err_invalid_vector_bool_decl_spec;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
TypeAltiVecBool = isAltiVecBool;
|
|
|
|
TSTLoc = Loc;
|
|
|
|
TSTNameLoc = Loc;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-02-07 06:42:48 +08:00
|
|
|
bool DeclSpec::SetTypeSpecError() {
|
|
|
|
TypeSpecType = TST_error;
|
2010-08-27 01:22:34 +08:00
|
|
|
TypeSpecOwned = false;
|
2009-02-07 06:42:48 +08:00
|
|
|
TSTLoc = SourceLocation();
|
2011-03-17 04:16:18 +08:00
|
|
|
TSTNameLoc = SourceLocation();
|
2009-02-07 06:42:48 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-11-28 13:18:46 +08:00
|
|
|
bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
|
2012-10-18 07:31:46 +08:00
|
|
|
unsigned &DiagID, const LangOptions &Lang) {
|
2013-11-13 14:57:53 +08:00
|
|
|
// Duplicates are permitted in C99 onwards, but are not permitted in C89 or
|
|
|
|
// C++. However, since this is likely not what the user intended, we will
|
|
|
|
// always warn. We do not need to set the qualifier's location since we
|
|
|
|
// already have it.
|
2012-08-29 04:55:40 +08:00
|
|
|
if (TypeQualifiers & T) {
|
2012-08-29 20:35:14 +08:00
|
|
|
bool IsExtension = true;
|
2012-10-18 07:31:46 +08:00
|
|
|
if (Lang.C99)
|
2012-08-29 20:35:14 +08:00
|
|
|
IsExtension = false;
|
2012-08-29 04:55:40 +08:00
|
|
|
return BadSpecifier(T, T, PrevSpec, DiagID, IsExtension);
|
|
|
|
}
|
2019-01-09 19:25:09 +08:00
|
|
|
|
|
|
|
return SetTypeQual(T, Loc);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc) {
|
2006-08-04 13:25:55 +08:00
|
|
|
TypeQualifiers |= T;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2006-11-28 13:18:46 +08:00
|
|
|
switch (T) {
|
2013-03-28 09:55:44 +08:00
|
|
|
case TQ_unspecified: break;
|
|
|
|
case TQ_const: TQ_constLoc = Loc; return false;
|
|
|
|
case TQ_restrict: TQ_restrictLoc = Loc; return false;
|
|
|
|
case TQ_volatile: TQ_volatileLoc = Loc; return false;
|
2016-05-12 02:38:21 +08:00
|
|
|
case TQ_unaligned: TQ_unalignedLoc = Loc; return false;
|
2016-05-26 18:06:01 +08:00
|
|
|
case TQ_atomic: TQ_atomicLoc = Loc; return false;
|
2006-11-28 13:18:46 +08:00
|
|
|
}
|
2013-03-28 09:55:44 +08:00
|
|
|
|
|
|
|
llvm_unreachable("Unknown type qualifier!");
|
2006-08-04 13:25:55 +08:00
|
|
|
}
|
2006-08-04 12:39:53 +08:00
|
|
|
|
2013-11-13 14:57:53 +08:00
|
|
|
bool DeclSpec::setFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec,
|
|
|
|
unsigned &DiagID) {
|
|
|
|
// 'inline inline' is ok. However, since this is likely not what the user
|
|
|
|
// intended, we will always warn, similar to duplicates of type qualifiers.
|
|
|
|
if (FS_inline_specified) {
|
|
|
|
DiagID = diag::warn_duplicate_declspec;
|
|
|
|
PrevSpec = "inline";
|
|
|
|
return true;
|
|
|
|
}
|
2006-11-28 12:33:46 +08:00
|
|
|
FS_inline_specified = true;
|
2006-11-28 13:12:07 +08:00
|
|
|
FS_inlineLoc = Loc;
|
2006-11-28 12:33:46 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-13 14:57:53 +08:00
|
|
|
bool DeclSpec::setFunctionSpecForceInline(SourceLocation Loc, const char *&PrevSpec,
|
|
|
|
unsigned &DiagID) {
|
|
|
|
if (FS_forceinline_specified) {
|
|
|
|
DiagID = diag::warn_duplicate_declspec;
|
|
|
|
PrevSpec = "__forceinline";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
FS_forceinline_specified = true;
|
|
|
|
FS_forceinlineLoc = Loc;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DeclSpec::setFunctionSpecVirtual(SourceLocation Loc,
|
|
|
|
const char *&PrevSpec,
|
|
|
|
unsigned &DiagID) {
|
|
|
|
// 'virtual virtual' is ok, but warn as this is likely not what the user
|
|
|
|
// intended.
|
|
|
|
if (FS_virtual_specified) {
|
|
|
|
DiagID = diag::warn_duplicate_declspec;
|
|
|
|
PrevSpec = "virtual";
|
|
|
|
return true;
|
|
|
|
}
|
2008-10-31 17:07:45 +08:00
|
|
|
FS_virtual_specified = true;
|
|
|
|
FS_virtualLoc = Loc;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-13 14:57:53 +08:00
|
|
|
bool DeclSpec::setFunctionSpecExplicit(SourceLocation Loc,
|
2019-05-09 11:59:21 +08:00
|
|
|
const char *&PrevSpec, unsigned &DiagID,
|
|
|
|
ExplicitSpecifier ExplicitSpec,
|
|
|
|
SourceLocation CloseParenLoc) {
|
|
|
|
assert((ExplicitSpec.getKind() == ExplicitSpecKind::ResolvedTrue ||
|
|
|
|
ExplicitSpec.getExpr()) &&
|
|
|
|
"invalid ExplicitSpecifier");
|
2013-11-13 14:57:53 +08:00
|
|
|
// 'explicit explicit' is ok, but warn as this is likely not what the user
|
|
|
|
// intended.
|
2019-05-09 11:59:21 +08:00
|
|
|
if (hasExplicitSpecifier()) {
|
|
|
|
DiagID = (ExplicitSpec.getExpr() || FS_explicit_specifier.getExpr())
|
|
|
|
? diag::err_duplicate_declspec
|
|
|
|
: diag::ext_warn_duplicate_declspec;
|
2013-11-13 14:57:53 +08:00
|
|
|
PrevSpec = "explicit";
|
|
|
|
return true;
|
|
|
|
}
|
2019-05-09 11:59:21 +08:00
|
|
|
FS_explicit_specifier = ExplicitSpec;
|
2008-10-31 17:07:45 +08:00
|
|
|
FS_explicitLoc = Loc;
|
2019-05-09 11:59:21 +08:00
|
|
|
FS_explicitCloseParenLoc = CloseParenLoc;
|
2008-10-31 17:07:45 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-11-13 14:57:53 +08:00
|
|
|
bool DeclSpec::setFunctionSpecNoreturn(SourceLocation Loc,
|
|
|
|
const char *&PrevSpec,
|
|
|
|
unsigned &DiagID) {
|
|
|
|
// '_Noreturn _Noreturn' is ok, but warn as this is likely not what the user
|
|
|
|
// intended.
|
|
|
|
if (FS_noreturn_specified) {
|
|
|
|
DiagID = diag::warn_duplicate_declspec;
|
|
|
|
PrevSpec = "_Noreturn";
|
|
|
|
return true;
|
|
|
|
}
|
2013-01-18 06:16:11 +08:00
|
|
|
FS_noreturn_specified = true;
|
|
|
|
FS_noreturnLoc = Loc;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-08-04 04:12:06 +08:00
|
|
|
bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
|
|
|
|
unsigned &DiagID) {
|
2009-05-06 12:46:28 +08:00
|
|
|
if (Friend_specified) {
|
|
|
|
PrevSpec = "friend";
|
2014-01-11 05:27:55 +08:00
|
|
|
// Keep the later location, so that we can later diagnose ill-formed
|
|
|
|
// declarations like 'friend class X friend;'. Per [class.friend]p3,
|
|
|
|
// 'friend' must be the first token in a friend declaration that is
|
|
|
|
// not a function declaration.
|
|
|
|
FriendLoc = Loc;
|
|
|
|
DiagID = diag::warn_duplicate_declspec;
|
2009-05-06 12:46:28 +08:00
|
|
|
return true;
|
|
|
|
}
|
2009-08-04 04:12:06 +08:00
|
|
|
|
2009-05-06 12:46:28 +08:00
|
|
|
Friend_specified = true;
|
|
|
|
FriendLoc = Loc;
|
|
|
|
return false;
|
|
|
|
}
|
2006-11-28 12:33:46 +08:00
|
|
|
|
2011-09-09 10:06:17 +08:00
|
|
|
bool DeclSpec::setModulePrivateSpec(SourceLocation Loc, const char *&PrevSpec,
|
|
|
|
unsigned &DiagID) {
|
|
|
|
if (isModulePrivateSpecified()) {
|
|
|
|
PrevSpec = "__module_private__";
|
2018-10-04 07:09:29 +08:00
|
|
|
DiagID = diag::ext_warn_duplicate_declspec;
|
2011-09-09 10:06:17 +08:00
|
|
|
return true;
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-09-09 10:06:17 +08:00
|
|
|
ModulePrivateLoc = Loc;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-06-14 16:56:20 +08:00
|
|
|
bool DeclSpec::SetConstexprSpec(ConstexprSpecKind ConstexprKind,
|
|
|
|
SourceLocation Loc, const char *&PrevSpec,
|
2009-11-05 23:47:02 +08:00
|
|
|
unsigned &DiagID) {
|
2019-06-15 04:19:29 +08:00
|
|
|
if (getConstexprSpecifier() != CSK_unspecified) {
|
|
|
|
if (getConstexprSpecifier() == CSK_consteval || ConstexprKind == CSK_consteval)
|
|
|
|
return BadSpecifier(ConstexprKind, getConstexprSpecifier(), PrevSpec, DiagID);
|
2014-01-11 05:27:55 +08:00
|
|
|
DiagID = diag::warn_duplicate_declspec;
|
|
|
|
PrevSpec = "constexpr";
|
|
|
|
return true;
|
|
|
|
}
|
2019-06-14 16:56:20 +08:00
|
|
|
ConstexprSpecifier = ConstexprKind;
|
2009-11-05 23:47:02 +08:00
|
|
|
ConstexprLoc = Loc;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-01-19 02:04:31 +08:00
|
|
|
void DeclSpec::SaveWrittenBuiltinSpecs() {
|
2018-01-02 02:23:28 +08:00
|
|
|
writtenBS.Sign = getTypeSpecSign();
|
|
|
|
writtenBS.Width = getTypeSpecWidth();
|
|
|
|
writtenBS.Type = getTypeSpecType();
|
2010-01-19 02:04:31 +08:00
|
|
|
// Search the list of attributes for the presence of a mode attribute.
|
2018-07-13 23:07:47 +08:00
|
|
|
writtenBS.ModeAttr = getAttributes().hasAttribute(ParsedAttr::AT_Mode);
|
2010-01-19 02:04:31 +08:00
|
|
|
}
|
|
|
|
|
2006-08-04 12:39:53 +08:00
|
|
|
/// Finish - This does final analysis of the declspec, rejecting things like
|
|
|
|
/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
|
|
|
|
/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method,
|
|
|
|
/// DeclSpec is guaranteed self-consistent, even if an error occurred.
|
2015-11-15 11:32:11 +08:00
|
|
|
void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
|
2010-01-19 02:04:31 +08:00
|
|
|
// Before possibly changing their values, save specs as written.
|
|
|
|
SaveWrittenBuiltinSpecs();
|
|
|
|
|
2019-05-07 15:36:07 +08:00
|
|
|
// Check the type specifier components first. No checking for an invalid
|
|
|
|
// type.
|
|
|
|
if (TypeSpecType == TST_error)
|
|
|
|
return;
|
2006-08-04 14:36:52 +08:00
|
|
|
|
2013-04-27 00:15:35 +08:00
|
|
|
// If decltype(auto) is used, no other type specifiers are permitted.
|
|
|
|
if (TypeSpecType == TST_decltype_auto &&
|
|
|
|
(TypeSpecWidth != TSW_unspecified ||
|
|
|
|
TypeSpecComplex != TSC_unspecified ||
|
|
|
|
TypeSpecSign != TSS_unspecified ||
|
|
|
|
TypeAltiVecVector || TypeAltiVecPixel || TypeAltiVecBool ||
|
|
|
|
TypeQualifiers)) {
|
2016-05-12 02:38:21 +08:00
|
|
|
const unsigned NumLocs = 9;
|
2013-04-27 00:15:35 +08:00
|
|
|
SourceLocation ExtraLocs[NumLocs] = {
|
2016-10-22 05:13:56 +08:00
|
|
|
TSWRange.getBegin(), TSCLoc, TSSLoc,
|
|
|
|
AltiVecLoc, TQ_constLoc, TQ_restrictLoc,
|
|
|
|
TQ_volatileLoc, TQ_atomicLoc, TQ_unalignedLoc};
|
2013-04-27 00:15:35 +08:00
|
|
|
FixItHint Hints[NumLocs];
|
|
|
|
SourceLocation FirstLoc;
|
|
|
|
for (unsigned I = 0; I != NumLocs; ++I) {
|
2015-10-03 13:15:57 +08:00
|
|
|
if (ExtraLocs[I].isValid()) {
|
2013-04-27 00:15:35 +08:00
|
|
|
if (FirstLoc.isInvalid() ||
|
2015-11-15 11:32:11 +08:00
|
|
|
S.getSourceManager().isBeforeInTranslationUnit(ExtraLocs[I],
|
|
|
|
FirstLoc))
|
2013-04-27 00:15:35 +08:00
|
|
|
FirstLoc = ExtraLocs[I];
|
|
|
|
Hints[I] = FixItHint::CreateRemoval(ExtraLocs[I]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TypeSpecWidth = TSW_unspecified;
|
|
|
|
TypeSpecComplex = TSC_unspecified;
|
|
|
|
TypeSpecSign = TSS_unspecified;
|
|
|
|
TypeAltiVecVector = TypeAltiVecPixel = TypeAltiVecBool = false;
|
|
|
|
TypeQualifiers = 0;
|
2015-11-15 11:32:11 +08:00
|
|
|
S.Diag(TSTLoc, diag::err_decltype_auto_cannot_be_combined)
|
2013-04-27 00:15:35 +08:00
|
|
|
<< Hints[0] << Hints[1] << Hints[2] << Hints[3]
|
|
|
|
<< Hints[4] << Hints[5] << Hints[6] << Hints[7];
|
|
|
|
}
|
|
|
|
|
2010-06-23 14:00:24 +08:00
|
|
|
// Validate and finalize AltiVec vector declspec.
|
|
|
|
if (TypeAltiVecVector) {
|
|
|
|
if (TypeAltiVecBool) {
|
|
|
|
// Sign specifiers are not allowed with vector bool. (PIM 2.1)
|
|
|
|
if (TypeSpecSign != TSS_unspecified) {
|
2015-11-15 11:32:11 +08:00
|
|
|
S.Diag(TSSLoc, diag::err_invalid_vector_bool_decl_spec)
|
2010-06-23 14:00:24 +08:00
|
|
|
<< getSpecifierName((TSS)TypeSpecSign);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only char/int are valid with vector bool. (PIM 2.1)
|
2010-06-24 03:34:52 +08:00
|
|
|
if (((TypeSpecType != TST_unspecified) && (TypeSpecType != TST_char) &&
|
|
|
|
(TypeSpecType != TST_int)) || TypeAltiVecPixel) {
|
2015-11-15 11:32:11 +08:00
|
|
|
S.Diag(TSTLoc, diag::err_invalid_vector_bool_decl_spec)
|
2010-06-23 14:00:24 +08:00
|
|
|
<< (TypeAltiVecPixel ? "__pixel" :
|
2014-01-15 17:15:43 +08:00
|
|
|
getSpecifierName((TST)TypeSpecType, Policy));
|
2010-06-23 14:00:24 +08:00
|
|
|
}
|
|
|
|
|
2015-03-04 04:08:43 +08:00
|
|
|
// Only 'short' and 'long long' are valid with vector bool. (PIM 2.1)
|
|
|
|
if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short) &&
|
|
|
|
(TypeSpecWidth != TSW_longlong))
|
2016-10-22 05:13:56 +08:00
|
|
|
S.Diag(TSWRange.getBegin(), diag::err_invalid_vector_bool_decl_spec)
|
|
|
|
<< getSpecifierName((TSW)TypeSpecWidth);
|
2010-06-23 14:00:24 +08:00
|
|
|
|
2015-07-30 22:08:36 +08:00
|
|
|
// vector bool long long requires VSX support or ZVector.
|
2015-03-11 23:57:19 +08:00
|
|
|
if ((TypeSpecWidth == TSW_longlong) &&
|
2015-11-15 11:32:11 +08:00
|
|
|
(!S.Context.getTargetInfo().hasFeature("vsx")) &&
|
|
|
|
(!S.Context.getTargetInfo().hasFeature("power8-vector")) &&
|
|
|
|
!S.getLangOpts().ZVector)
|
|
|
|
S.Diag(TSTLoc, diag::err_invalid_vector_long_long_decl_spec);
|
2015-03-04 04:08:43 +08:00
|
|
|
|
2010-06-23 14:00:24 +08:00
|
|
|
// Elements of vector bool are interpreted as unsigned. (PIM 2.1)
|
|
|
|
if ((TypeSpecType == TST_char) || (TypeSpecType == TST_int) ||
|
|
|
|
(TypeSpecWidth != TSW_unspecified))
|
|
|
|
TypeSpecSign = TSS_unsigned;
|
[PowerPC] Initial VSX intrinsic support, with min/max for vector double
Now that we have initial support for VSX, we can begin adding
intrinsics for programmer access to VSX instructions. This patch
performs the necessary enablement in the front end, and tests it by
implementing intrinsics for minimum and maximum using the vector
double data type.
The main change in the front end is to no longer disallow "vector" and
"double" in the same declaration (lib/Sema/DeclSpec.cpp), but "vector"
and "long double" must still be disallowed. The new intrinsics are
accessed via vec_max and vec_min with changes in
lib/Headers/altivec.h. Note that for v4f32, we already access
corresponding VMX builtins, but with VSX enabled we should use the
forms that allow all 64 vector registers.
The new built-ins are defined in include/clang/Basic/BuiltinsPPC.def.
I've added a new test in test/CodeGen/builtins-ppc-vsx.c that is
similar to, but much smaller than, builtins-ppc-altivec.c. This
allows us to test VSX IR generation without duplicating CHECK lines
for the existing bazillion Altivec tests.
Since vector double is now legal when VSX is available, I've modified
the error message, and changed where we test for it and for vector
long double, since the target machine isn't visible in the old place.
This serendipitously removed a not-pertinent warning about 'long'
being deprecated when used with 'vector', when "vector long double" is
encountered and we just want to issue an error. The existing tests
test/Parser/altivec.c and test/Parser/cxx-altivec.cpp have been
updated accordingly, and I've added test/Parser/vsx.c to verify that
"vector double" is now legitimate with VSX enabled.
There is a companion patch for LLVM.
llvm-svn: 220989
2014-11-01 03:19:24 +08:00
|
|
|
} else if (TypeSpecType == TST_double) {
|
|
|
|
// vector long double and vector long long double are never allowed.
|
2015-07-30 22:08:36 +08:00
|
|
|
// vector double is OK for Power7 and later, and ZVector.
|
[PowerPC] Initial VSX intrinsic support, with min/max for vector double
Now that we have initial support for VSX, we can begin adding
intrinsics for programmer access to VSX instructions. This patch
performs the necessary enablement in the front end, and tests it by
implementing intrinsics for minimum and maximum using the vector
double data type.
The main change in the front end is to no longer disallow "vector" and
"double" in the same declaration (lib/Sema/DeclSpec.cpp), but "vector"
and "long double" must still be disallowed. The new intrinsics are
accessed via vec_max and vec_min with changes in
lib/Headers/altivec.h. Note that for v4f32, we already access
corresponding VMX builtins, but with VSX enabled we should use the
forms that allow all 64 vector registers.
The new built-ins are defined in include/clang/Basic/BuiltinsPPC.def.
I've added a new test in test/CodeGen/builtins-ppc-vsx.c that is
similar to, but much smaller than, builtins-ppc-altivec.c. This
allows us to test VSX IR generation without duplicating CHECK lines
for the existing bazillion Altivec tests.
Since vector double is now legal when VSX is available, I've modified
the error message, and changed where we test for it and for vector
long double, since the target machine isn't visible in the old place.
This serendipitously removed a not-pertinent warning about 'long'
being deprecated when used with 'vector', when "vector long double" is
encountered and we just want to issue an error. The existing tests
test/Parser/altivec.c and test/Parser/cxx-altivec.cpp have been
updated accordingly, and I've added test/Parser/vsx.c to verify that
"vector double" is now legitimate with VSX enabled.
There is a companion patch for LLVM.
llvm-svn: 220989
2014-11-01 03:19:24 +08:00
|
|
|
if (TypeSpecWidth == TSW_long || TypeSpecWidth == TSW_longlong)
|
2016-10-22 05:13:56 +08:00
|
|
|
S.Diag(TSWRange.getBegin(),
|
|
|
|
diag::err_invalid_vector_long_double_decl_spec);
|
2015-11-15 11:32:11 +08:00
|
|
|
else if (!S.Context.getTargetInfo().hasFeature("vsx") &&
|
|
|
|
!S.getLangOpts().ZVector)
|
|
|
|
S.Diag(TSTLoc, diag::err_invalid_vector_double_decl_spec);
|
2015-07-30 22:08:36 +08:00
|
|
|
} else if (TypeSpecType == TST_float) {
|
2017-07-18 01:46:47 +08:00
|
|
|
// vector float is unsupported for ZVector unless we have the
|
|
|
|
// vector-enhancements facility 1 (ISA revision 12).
|
|
|
|
if (S.getLangOpts().ZVector &&
|
|
|
|
!S.Context.getTargetInfo().hasFeature("arch12"))
|
2015-11-15 11:32:11 +08:00
|
|
|
S.Diag(TSTLoc, diag::err_invalid_vector_float_decl_spec);
|
2014-08-24 12:50:19 +08:00
|
|
|
} else if (TypeSpecWidth == TSW_long) {
|
2015-07-30 22:08:36 +08:00
|
|
|
// vector long is unsupported for ZVector and deprecated for AltiVec.
|
2015-11-15 11:32:11 +08:00
|
|
|
if (S.getLangOpts().ZVector)
|
2016-10-22 05:13:56 +08:00
|
|
|
S.Diag(TSWRange.getBegin(), diag::err_invalid_vector_long_decl_spec);
|
2015-07-30 22:08:36 +08:00
|
|
|
else
|
2016-10-22 05:13:56 +08:00
|
|
|
S.Diag(TSWRange.getBegin(),
|
|
|
|
diag::warn_vector_long_decl_spec_combination)
|
|
|
|
<< getSpecifierName((TST)TypeSpecType, Policy);
|
2010-06-23 14:00:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (TypeAltiVecPixel) {
|
|
|
|
//TODO: perform validation
|
|
|
|
TypeSpecType = TST_int;
|
|
|
|
TypeSpecSign = TSS_unsigned;
|
|
|
|
TypeSpecWidth = TSW_short;
|
2010-08-27 01:22:34 +08:00
|
|
|
TypeSpecOwned = false;
|
2010-06-23 14:00:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-14 22:53:51 +08:00
|
|
|
bool IsFixedPointType =
|
|
|
|
TypeSpecType == TST_accum || TypeSpecType == TST_fract;
|
|
|
|
|
2018-06-05 00:07:52 +08:00
|
|
|
// signed/unsigned are only valid with int/char/wchar_t/_Accum.
|
2006-08-04 14:15:52 +08:00
|
|
|
if (TypeSpecSign != TSS_unspecified) {
|
2006-08-04 14:36:52 +08:00
|
|
|
if (TypeSpecType == TST_unspecified)
|
|
|
|
TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int.
|
2018-06-05 00:07:52 +08:00
|
|
|
else if (TypeSpecType != TST_int && TypeSpecType != TST_int128 &&
|
|
|
|
TypeSpecType != TST_char && TypeSpecType != TST_wchar &&
|
2018-06-14 22:53:51 +08:00
|
|
|
!IsFixedPointType) {
|
2015-11-15 11:32:11 +08:00
|
|
|
S.Diag(TSSLoc, diag::err_invalid_sign_spec)
|
2014-01-15 17:15:43 +08:00
|
|
|
<< getSpecifierName((TST)TypeSpecType, Policy);
|
2006-08-04 14:36:52 +08:00
|
|
|
// signed double -> double.
|
2006-08-04 14:15:52 +08:00
|
|
|
TypeSpecSign = TSS_unspecified;
|
|
|
|
}
|
|
|
|
}
|
2006-08-04 14:36:52 +08:00
|
|
|
|
2006-08-04 14:15:52 +08:00
|
|
|
// Validate the width of the type.
|
2018-01-02 02:23:28 +08:00
|
|
|
switch (TypeSpecWidth) {
|
2006-08-04 14:15:52 +08:00
|
|
|
case TSW_unspecified: break;
|
|
|
|
case TSW_short: // short int
|
|
|
|
case TSW_longlong: // long long int
|
2006-08-04 14:36:52 +08:00
|
|
|
if (TypeSpecType == TST_unspecified)
|
|
|
|
TypeSpecType = TST_int; // short -> short int, long long -> long long int.
|
2018-06-05 00:07:52 +08:00
|
|
|
else if (!(TypeSpecType == TST_int ||
|
2018-06-14 22:53:51 +08:00
|
|
|
(IsFixedPointType && TypeSpecWidth != TSW_longlong))) {
|
2016-10-22 05:13:56 +08:00
|
|
|
S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec)
|
|
|
|
<< (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy);
|
2006-08-04 14:15:52 +08:00
|
|
|
TypeSpecType = TST_int;
|
2018-06-14 22:53:51 +08:00
|
|
|
TypeSpecSat = false;
|
2010-08-27 01:22:34 +08:00
|
|
|
TypeSpecOwned = false;
|
2006-08-04 14:15:52 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TSW_long: // long double, long int
|
2006-08-04 14:36:52 +08:00
|
|
|
if (TypeSpecType == TST_unspecified)
|
|
|
|
TypeSpecType = TST_int; // long -> long int.
|
2018-06-05 00:07:52 +08:00
|
|
|
else if (TypeSpecType != TST_int && TypeSpecType != TST_double &&
|
2018-06-14 22:53:51 +08:00
|
|
|
!IsFixedPointType) {
|
2016-10-22 05:13:56 +08:00
|
|
|
S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec)
|
|
|
|
<< (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy);
|
2006-08-04 14:15:52 +08:00
|
|
|
TypeSpecType = TST_int;
|
2018-06-14 22:53:51 +08:00
|
|
|
TypeSpecSat = false;
|
2010-08-27 01:22:34 +08:00
|
|
|
TypeSpecOwned = false;
|
2006-08-04 14:15:52 +08:00
|
|
|
}
|
2006-08-04 14:36:52 +08:00
|
|
|
break;
|
2006-08-04 14:15:52 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2006-08-14 03:58:17 +08:00
|
|
|
// TODO: if the implementation does not implement _Complex or _Imaginary,
|
2006-08-04 14:36:52 +08:00
|
|
|
// disallow their use. Need information about the backend.
|
|
|
|
if (TypeSpecComplex != TSC_unspecified) {
|
|
|
|
if (TypeSpecType == TST_unspecified) {
|
2015-11-15 11:32:11 +08:00
|
|
|
S.Diag(TSCLoc, diag::ext_plain_complex)
|
2010-04-01 01:46:05 +08:00
|
|
|
<< FixItHint::CreateInsertion(
|
2015-11-15 11:32:11 +08:00
|
|
|
S.getLocForEndOfToken(getTypeSpecComplexLoc()),
|
2009-04-02 06:41:11 +08:00
|
|
|
" double");
|
2006-08-04 14:36:52 +08:00
|
|
|
TypeSpecType = TST_double; // _Complex -> _Complex double.
|
|
|
|
} else if (TypeSpecType == TST_int || TypeSpecType == TST_char) {
|
2006-08-05 11:28:50 +08:00
|
|
|
// Note that this intentionally doesn't include _Complex _Bool.
|
2015-11-15 11:32:11 +08:00
|
|
|
if (!S.getLangOpts().CPlusPlus)
|
|
|
|
S.Diag(TSTLoc, diag::ext_integer_complex);
|
2006-08-04 14:36:52 +08:00
|
|
|
} else if (TypeSpecType != TST_float && TypeSpecType != TST_double) {
|
2015-11-15 11:32:11 +08:00
|
|
|
S.Diag(TSCLoc, diag::err_invalid_complex_spec)
|
2014-01-15 17:15:43 +08:00
|
|
|
<< getSpecifierName((TST)TypeSpecType, Policy);
|
2006-08-04 14:36:52 +08:00
|
|
|
TypeSpecComplex = TSC_unspecified;
|
|
|
|
}
|
|
|
|
}
|
2006-08-05 11:30:45 +08:00
|
|
|
|
2013-04-13 06:46:28 +08:00
|
|
|
// C11 6.7.1/3, C++11 [dcl.stc]p1, GNU TLS: __thread, thread_local and
|
|
|
|
// _Thread_local can only appear with the 'static' and 'extern' storage class
|
|
|
|
// specifiers. We also allow __private_extern__ as an extension.
|
|
|
|
if (ThreadStorageClassSpec != TSCS_unspecified) {
|
|
|
|
switch (StorageClassSpec) {
|
|
|
|
case SCS_unspecified:
|
|
|
|
case SCS_extern:
|
|
|
|
case SCS_private_extern:
|
|
|
|
case SCS_static:
|
|
|
|
break;
|
|
|
|
default:
|
2015-11-15 11:32:11 +08:00
|
|
|
if (S.getSourceManager().isBeforeInTranslationUnit(
|
2013-04-13 06:46:28 +08:00
|
|
|
getThreadStorageClassSpecLoc(), getStorageClassSpecLoc()))
|
2015-11-15 11:32:11 +08:00
|
|
|
S.Diag(getStorageClassSpecLoc(),
|
2013-04-13 06:46:28 +08:00
|
|
|
diag::err_invalid_decl_spec_combination)
|
|
|
|
<< DeclSpec::getSpecifierName(getThreadStorageClassSpec())
|
|
|
|
<< SourceRange(getThreadStorageClassSpecLoc());
|
|
|
|
else
|
2015-11-15 11:32:11 +08:00
|
|
|
S.Diag(getThreadStorageClassSpecLoc(),
|
2013-04-13 06:46:28 +08:00
|
|
|
diag::err_invalid_decl_spec_combination)
|
|
|
|
<< DeclSpec::getSpecifierName(getStorageClassSpec())
|
|
|
|
<< SourceRange(getStorageClassSpecLoc());
|
|
|
|
// Discard the thread storage class specifier to recover.
|
|
|
|
ThreadStorageClassSpec = TSCS_unspecified;
|
|
|
|
ThreadStorageClassSpecLoc = SourceLocation();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-05 03:54:14 +08:00
|
|
|
// If no type specifier was provided and we're parsing a language where
|
|
|
|
// the type specifier is not optional, but we got 'auto' as a storage
|
|
|
|
// class specifier, then assume this is an attempt to use C++0x's 'auto'
|
|
|
|
// type specifier.
|
2015-11-15 11:32:11 +08:00
|
|
|
if (S.getLangOpts().CPlusPlus &&
|
2011-09-05 03:54:14 +08:00
|
|
|
TypeSpecType == TST_unspecified && StorageClassSpec == SCS_auto) {
|
|
|
|
TypeSpecType = TST_auto;
|
2013-04-04 03:27:57 +08:00
|
|
|
StorageClassSpec = SCS_unspecified;
|
2011-09-05 03:54:14 +08:00
|
|
|
TSTLoc = TSTNameLoc = StorageClassSpecLoc;
|
|
|
|
StorageClassSpecLoc = SourceLocation();
|
|
|
|
}
|
|
|
|
// Diagnose if we've recovered from an ill-formed 'auto' storage class
|
2013-04-27 00:15:35 +08:00
|
|
|
// specifier in a pre-C++11 dialect of C++.
|
2015-11-15 11:32:11 +08:00
|
|
|
if (!S.getLangOpts().CPlusPlus11 && TypeSpecType == TST_auto)
|
|
|
|
S.Diag(TSTLoc, diag::ext_auto_type_specifier);
|
|
|
|
if (S.getLangOpts().CPlusPlus && !S.getLangOpts().CPlusPlus11 &&
|
2011-09-05 03:54:14 +08:00
|
|
|
StorageClassSpec == SCS_auto)
|
2015-11-15 11:32:11 +08:00
|
|
|
S.Diag(StorageClassSpecLoc, diag::warn_auto_storage_class)
|
2011-09-05 03:54:14 +08:00
|
|
|
<< FixItHint::CreateRemoval(StorageClassSpecLoc);
|
2018-05-01 13:02:45 +08:00
|
|
|
if (TypeSpecType == TST_char8)
|
|
|
|
S.Diag(TSTLoc, diag::warn_cxx17_compat_unicode_type);
|
|
|
|
else if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32)
|
2015-11-15 11:32:11 +08:00
|
|
|
S.Diag(TSTLoc, diag::warn_cxx98_compat_unicode_type)
|
2011-10-18 07:06:20 +08:00
|
|
|
<< (TypeSpecType == TST_char16 ? "char16_t" : "char32_t");
|
2019-06-14 16:56:20 +08:00
|
|
|
if (getConstexprSpecifier() == CSK_constexpr)
|
2015-11-15 11:32:11 +08:00
|
|
|
S.Diag(ConstexprLoc, diag::warn_cxx98_compat_constexpr);
|
2019-06-14 16:56:20 +08:00
|
|
|
if (getConstexprSpecifier() == CSK_consteval)
|
|
|
|
S.Diag(ConstexprLoc, diag::warn_cxx20_compat_consteval);
|
2009-08-06 10:15:43 +08:00
|
|
|
// C++ [class.friend]p6:
|
|
|
|
// No storage-class-specifier shall appear in the decl-specifier-seq
|
|
|
|
// of a friend declaration.
|
2013-04-13 06:46:28 +08:00
|
|
|
if (isFriendSpecified() &&
|
|
|
|
(getStorageClassSpec() || getThreadStorageClassSpec())) {
|
|
|
|
SmallString<32> SpecName;
|
|
|
|
SourceLocation SCLoc;
|
|
|
|
FixItHint StorageHint, ThreadHint;
|
|
|
|
|
|
|
|
if (DeclSpec::SCS SC = getStorageClassSpec()) {
|
|
|
|
SpecName = getSpecifierName(SC);
|
|
|
|
SCLoc = getStorageClassSpecLoc();
|
|
|
|
StorageHint = FixItHint::CreateRemoval(SCLoc);
|
|
|
|
}
|
2009-08-06 10:15:43 +08:00
|
|
|
|
2013-04-13 06:46:28 +08:00
|
|
|
if (DeclSpec::TSCS TSC = getThreadStorageClassSpec()) {
|
|
|
|
if (!SpecName.empty()) SpecName += " ";
|
|
|
|
SpecName += getSpecifierName(TSC);
|
|
|
|
SCLoc = getThreadStorageClassSpecLoc();
|
|
|
|
ThreadHint = FixItHint::CreateRemoval(SCLoc);
|
|
|
|
}
|
2009-08-06 10:15:43 +08:00
|
|
|
|
2015-11-15 11:32:11 +08:00
|
|
|
S.Diag(SCLoc, diag::err_friend_decl_spec)
|
2013-04-13 06:46:28 +08:00
|
|
|
<< SpecName << StorageHint << ThreadHint;
|
2009-08-06 10:15:43 +08:00
|
|
|
|
|
|
|
ClearStorageClassSpecs();
|
|
|
|
}
|
|
|
|
|
2014-05-01 02:24:01 +08:00
|
|
|
// C++11 [dcl.fct.spec]p5:
|
|
|
|
// The virtual specifier shall be used only in the initial
|
|
|
|
// declaration of a non-static class member function;
|
|
|
|
// C++11 [dcl.fct.spec]p6:
|
|
|
|
// The explicit specifier shall be used only in the declaration of
|
|
|
|
// a constructor or conversion function within its class
|
|
|
|
// definition;
|
2019-05-09 11:59:21 +08:00
|
|
|
if (isFriendSpecified() && (isVirtualSpecified() || hasExplicitSpecifier())) {
|
2014-05-01 02:24:01 +08:00
|
|
|
StringRef Keyword;
|
2019-05-09 11:59:21 +08:00
|
|
|
FixItHint Hint;
|
2014-05-01 02:24:01 +08:00
|
|
|
SourceLocation SCLoc;
|
|
|
|
|
|
|
|
if (isVirtualSpecified()) {
|
|
|
|
Keyword = "virtual";
|
|
|
|
SCLoc = getVirtualSpecLoc();
|
2019-05-09 11:59:21 +08:00
|
|
|
Hint = FixItHint::CreateRemoval(SCLoc);
|
2014-05-01 02:24:01 +08:00
|
|
|
} else {
|
|
|
|
Keyword = "explicit";
|
|
|
|
SCLoc = getExplicitSpecLoc();
|
2019-05-09 11:59:21 +08:00
|
|
|
Hint = FixItHint::CreateRemoval(getExplicitSpecRange());
|
2014-05-01 02:24:01 +08:00
|
|
|
}
|
|
|
|
|
2015-11-15 11:32:11 +08:00
|
|
|
S.Diag(SCLoc, diag::err_friend_decl_spec)
|
2014-05-01 02:24:01 +08:00
|
|
|
<< Keyword << Hint;
|
|
|
|
|
2019-05-09 11:59:21 +08:00
|
|
|
FS_virtual_specified = false;
|
|
|
|
FS_explicit_specifier = ExplicitSpecifier();
|
2014-05-01 02:24:01 +08:00
|
|
|
FS_virtualLoc = FS_explicitLoc = SourceLocation();
|
|
|
|
}
|
|
|
|
|
2011-09-10 05:14:29 +08:00
|
|
|
assert(!TypeSpecOwned || isDeclRep((TST) TypeSpecType));
|
2014-05-01 02:24:01 +08:00
|
|
|
|
2006-08-05 11:30:45 +08:00
|
|
|
// Okay, now we can infer the real type.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2006-08-14 03:58:17 +08:00
|
|
|
// TODO: return "auto function" and other bad things based on the real type.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2006-08-04 14:42:31 +08:00
|
|
|
// 'data definition has no type or storage class'?
|
2006-08-04 12:39:53 +08:00
|
|
|
}
|
2008-08-11 11:45:03 +08:00
|
|
|
|
2008-12-28 23:28:59 +08:00
|
|
|
bool DeclSpec::isMissingDeclaratorOk() {
|
|
|
|
TST tst = getTypeSpecType();
|
2014-06-09 10:04:02 +08:00
|
|
|
return isDeclRep(tst) && getRepAsDecl() != nullptr &&
|
2010-08-24 13:47:05 +08:00
|
|
|
StorageClassSpec != DeclSpec::SCS_typedef;
|
2008-12-28 23:28:59 +08:00
|
|
|
}
|
2009-11-03 09:35:08 +08:00
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc,
|
2009-11-03 09:35:08 +08:00
|
|
|
OverloadedOperatorKind Op,
|
|
|
|
SourceLocation SymbolLocations[3]) {
|
2017-12-30 12:15:27 +08:00
|
|
|
Kind = UnqualifiedIdKind::IK_OperatorFunctionId;
|
2009-11-03 09:35:08 +08:00
|
|
|
StartLocation = OperatorLoc;
|
|
|
|
EndLocation = OperatorLoc;
|
|
|
|
OperatorFunctionId.Operator = Op;
|
|
|
|
for (unsigned I = 0; I != 3; ++I) {
|
|
|
|
OperatorFunctionId.SymbolLocations[I] = SymbolLocations[I].getRawEncoding();
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-11-03 09:35:08 +08:00
|
|
|
if (SymbolLocations[I].isValid())
|
|
|
|
EndLocation = SymbolLocations[I];
|
|
|
|
}
|
|
|
|
}
|
2011-01-17 11:05:47 +08:00
|
|
|
|
2011-01-23 00:56:46 +08:00
|
|
|
bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc,
|
2011-01-22 23:58:16 +08:00
|
|
|
const char *&PrevSpec) {
|
2015-03-25 08:53:27 +08:00
|
|
|
if (!FirstLocation.isValid())
|
|
|
|
FirstLocation = Loc;
|
2011-03-09 01:10:18 +08:00
|
|
|
LastLocation = Loc;
|
2015-03-25 08:53:27 +08:00
|
|
|
LastSpecifier = VS;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-01-17 11:05:47 +08:00
|
|
|
if (Specifiers & VS) {
|
|
|
|
PrevSpec = getSpecifierName(VS);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
Specifiers |= VS;
|
|
|
|
|
|
|
|
switch (VS) {
|
2011-09-23 13:06:16 +08:00
|
|
|
default: llvm_unreachable("Unknown specifier!");
|
2011-01-17 11:05:47 +08:00
|
|
|
case VS_Override: VS_overrideLoc = Loc; break;
|
2016-07-29 18:42:48 +08:00
|
|
|
case VS_GNU_Final:
|
2013-10-18 08:33:31 +08:00
|
|
|
case VS_Sealed:
|
2011-01-17 11:05:47 +08:00
|
|
|
case VS_Final: VS_finalLoc = Loc; break;
|
|
|
|
}
|
2011-01-22 23:58:16 +08:00
|
|
|
|
2011-01-17 11:05:47 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-01-23 00:56:46 +08:00
|
|
|
const char *VirtSpecifiers::getSpecifierName(Specifier VS) {
|
2011-01-22 23:11:37 +08:00
|
|
|
switch (VS) {
|
2011-09-23 13:06:16 +08:00
|
|
|
default: llvm_unreachable("Unknown specifier");
|
2011-01-22 23:11:37 +08:00
|
|
|
case VS_Override: return "override";
|
|
|
|
case VS_Final: return "final";
|
2016-07-29 18:42:48 +08:00
|
|
|
case VS_GNU_Final: return "__final";
|
2013-10-18 08:33:31 +08:00
|
|
|
case VS_Sealed: return "sealed";
|
2011-01-22 23:11:37 +08:00
|
|
|
}
|
|
|
|
}
|