Import Clang r73070.
This commit is contained in:
parent
70b4596d9d
commit
8ba99c0032
@ -52,22 +52,16 @@ td {
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#cxx">C++ Language Features</a>
|
||||
<ul>
|
||||
<li>...</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#objcxx">Objective C++ Language Features</a>
|
||||
<ul>
|
||||
<li>...</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#target_features">Target-Specific Features and Limitations</a>
|
||||
<ul>
|
||||
<li><a href="#target_arch">CPU Architectures Features and Limitations</a>
|
||||
<ul>
|
||||
<li><a href="#target_arch_x86">X86</a></li>
|
||||
<li>PPC</li>
|
||||
<li>ARM</li>
|
||||
<li><a href="#target_arch_arm">ARM</a></li>
|
||||
<li><a href="#target_arch_other">Other platforms</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#target_os">Operating System Features and Limitations</a>
|
||||
@ -612,9 +606,10 @@ translation units.</p>
|
||||
|
||||
<p>clang has some experimental support for extensions from
|
||||
Microsoft Visual C++; to enable it, use the -fms-extensions command-line
|
||||
option. Eventually, this will be the default for Windows targets.
|
||||
These extensions are not anywhere near complete, so please do not
|
||||
file bugs; patches are welcome, though.</p>
|
||||
option. This is the default for Windows targets. Note that the
|
||||
support is incomplete; enabling Microsoft extensions will silently drop
|
||||
certain constructs (including __declspec and Microsoft-style asm statements).
|
||||
</p>
|
||||
|
||||
<li>clang does not support the Microsoft extension where anonymous
|
||||
record members can be declared using user defined typedefs.</li>
|
||||
@ -670,7 +665,37 @@ more information.</p>
|
||||
<!-- ======================== -->
|
||||
<h4 id="target_arch_x86">X86</h4>
|
||||
<!-- ======================== -->
|
||||
<p>The support for X86 (both 32-bit and 64-bit) is considered stable
|
||||
on Darwin (Mac OS/X), Linux, FreeBSD, and Dragonfly BSD: it has been tested to
|
||||
correctly compile large C and Objective-C codebases. (FIXME: Anything specific
|
||||
we want to say here? Possibly mention some LLVM x86 limitations?)
|
||||
|
||||
<!-- ======================== -->
|
||||
<h4 id="target_arch_arm">ARM</h4>
|
||||
<!-- ======================== -->
|
||||
ARM support is mostly feature-complete, but still experimental; it hasn't
|
||||
undergone significant testing.
|
||||
|
||||
<!-- ======================== -->
|
||||
<h4 id="target_arch_other">Other platforms</h4>
|
||||
<!-- ======================== -->
|
||||
clang currently contains some support for PPC and Sparc; however, significant
|
||||
pieces of code generation are still missing, and they haven't undergone
|
||||
significant testing.
|
||||
|
||||
<p>clang contains some support for the embedded PIC16 processor
|
||||
(FIXME: I haven't been keeping track of this; what should this say?).
|
||||
|
||||
<p>clang contains limited support for the MSP430 embedded processor, but both
|
||||
the clang support and the LLVM backend support are highly experimental.
|
||||
|
||||
<p>Other platforms are completely unsupported at the moment. Adding the
|
||||
minimal support needed for parsing and semantic analysis on a new platform
|
||||
is quite easy; see lib/Basic/Targets.cpp in the clang source tree. This level
|
||||
of support is also sufficient for conversion to LLVM IR for simple programs.
|
||||
Proper support for conversion to LLVM IR requires adding code to
|
||||
lib/CodeGen/CGCall.cpp at the moment; this is likely to change soon, though.
|
||||
Generating assembly requires a suitable LLVM backend.
|
||||
|
||||
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
|
||||
<h3 id="target_os">Operating System Features and Limitations</h3>
|
||||
|
@ -696,7 +696,6 @@ class ASTContext {
|
||||
|
||||
/// Compatibility predicates used to check assignment expressions.
|
||||
bool typesAreCompatible(QualType, QualType); // C99 6.2.7p1
|
||||
bool typesAreBlockCompatible(QualType lhs, QualType rhs);
|
||||
|
||||
bool isObjCIdType(QualType T) const {
|
||||
return T == ObjCIdType;
|
||||
|
@ -34,6 +34,8 @@ class ObjCStringLiteral : public Expr {
|
||||
explicit ObjCStringLiteral(EmptyShell Empty)
|
||||
: Expr(ObjCStringLiteralClass, Empty) {}
|
||||
|
||||
ObjCStringLiteral* Clone(ASTContext &C) const;
|
||||
|
||||
StringLiteral *getString() { return cast<StringLiteral>(String); }
|
||||
const StringLiteral *getString() const { return cast<StringLiteral>(String); }
|
||||
void setString(StringLiteral *S) { String = S; }
|
||||
@ -64,7 +66,8 @@ class ObjCEncodeExpr : public Expr {
|
||||
public:
|
||||
ObjCEncodeExpr(QualType T, QualType ET,
|
||||
SourceLocation at, SourceLocation rp)
|
||||
: Expr(ObjCEncodeExprClass, T), EncType(ET), AtLoc(at), RParenLoc(rp) {}
|
||||
: Expr(ObjCEncodeExprClass, T, ET->isDependentType(),
|
||||
ET->isDependentType()), EncType(ET), AtLoc(at), RParenLoc(rp) {}
|
||||
|
||||
explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){}
|
||||
|
||||
@ -103,6 +106,8 @@ class ObjCSelectorExpr : public Expr {
|
||||
explicit ObjCSelectorExpr(EmptyShell Empty)
|
||||
: Expr(ObjCSelectorExprClass, Empty) {}
|
||||
|
||||
ObjCSelectorExpr *Clone(ASTContext &C) const;
|
||||
|
||||
Selector getSelector() const { return SelName; }
|
||||
void setSelector(Selector S) { SelName = S; }
|
||||
|
||||
@ -143,6 +148,8 @@ class ObjCProtocolExpr : public Expr {
|
||||
explicit ObjCProtocolExpr(EmptyShell Empty)
|
||||
: Expr(ObjCProtocolExprClass, Empty) {}
|
||||
|
||||
ObjCProtocolExpr *Clone(ASTContext &C) const;
|
||||
|
||||
ObjCProtocolDecl *getProtocol() const { return Protocol; }
|
||||
void setProtocol(ObjCProtocolDecl *P) { Protocol = P; }
|
||||
|
||||
|
@ -249,14 +249,11 @@ BUILTIN(__builtin_ia32_psradi128, "V4iV4ii", "")
|
||||
BUILTIN(__builtin_ia32_pmaddwd128, "V8sV8sV8s", "")
|
||||
BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "")
|
||||
BUILTIN(__builtin_ia32_mwait, "vUiUi", "")
|
||||
BUILTIN(__builtin_ia32_movshdup, "V4fV4f", "")
|
||||
BUILTIN(__builtin_ia32_movsldup, "V4fV4f", "")
|
||||
BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "")
|
||||
BUILTIN(__builtin_ia32_palignr128, "V2LLiV2LLiV2LLii", "")
|
||||
BUILTIN(__builtin_ia32_palignr, "V1LLiV1LLiV1LLis", "")
|
||||
BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "")
|
||||
|
||||
BUILTIN(__builtin_ia32_loadlv4si, "V4iV2i*", "")
|
||||
BUILTIN(__builtin_ia32_storelv4si, "vV2i*V2LLi", "")
|
||||
|
||||
BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "")
|
||||
|
@ -85,9 +85,10 @@ def Trigraphs : DiagGroup<"trigraphs">;
|
||||
def : DiagGroup<"type-limits">;
|
||||
def Uninitialized : DiagGroup<"uninitialized">;
|
||||
def UnknownPragmas : DiagGroup<"unknown-pragmas">;
|
||||
def : DiagGroup<"unused-function">;
|
||||
def : DiagGroup<"unused-label">;
|
||||
def : DiagGroup<"unused-parameter">;
|
||||
def UnusedArgument : DiagGroup<"unused-argument">;
|
||||
def UnusedFunction : DiagGroup<"unused-function">;
|
||||
def UnusedLabel : DiagGroup<"unused-label">;
|
||||
def UnusedParameter : DiagGroup<"unused-parameter">;
|
||||
def UnusedValue : DiagGroup<"unused-value">;
|
||||
def UnusedVariable : DiagGroup<"unused-variable">;
|
||||
def : DiagGroup<"variadic-macros">;
|
||||
@ -98,6 +99,10 @@ def : DiagGroup<"write-strings">;
|
||||
// Aggregation warning settings.
|
||||
|
||||
|
||||
def Unused : DiagGroup<"unused",
|
||||
[UnusedArgument, UnusedFunction, UnusedLabel,
|
||||
UnusedParameter, UnusedValue, UnusedVariable]>;
|
||||
|
||||
// Format settings.
|
||||
def Format : DiagGroup<"format", [FormatExtraArgs, FormatZeroLength, NonNull]>;
|
||||
def FormatSecurity : DiagGroup<"format-security", [Format]>;
|
||||
|
@ -341,7 +341,6 @@ ALIAS("__attribute__", __attribute, KEYALL)
|
||||
ALIAS("__const" , const , KEYALL)
|
||||
ALIAS("__const__" , const , KEYALL)
|
||||
ALIAS("__alignof__" , __alignof , KEYALL)
|
||||
ALIAS("_asm" , asm , KEYMS)
|
||||
ALIAS("__asm" , asm , KEYALL)
|
||||
ALIAS("__asm__" , asm , KEYALL)
|
||||
ALIAS("__complex" , _Complex , KEYALL)
|
||||
@ -359,6 +358,11 @@ ALIAS("__typeof__" , typeof , KEYALL)
|
||||
ALIAS("__volatile" , volatile , KEYALL)
|
||||
ALIAS("__volatile__" , volatile , KEYALL)
|
||||
|
||||
// Microsoft extensions which should be disabled in strict conformance mode
|
||||
ALIAS("_asm" , asm , KEYMS)
|
||||
ALIAS("_cdecl" , __cdecl , KEYMS)
|
||||
ALIAS("_fastcall" , __fastcall , KEYMS)
|
||||
ALIAS("_stdcall" , __stdcall , KEYMS)
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Objective-C @-preceeded keywords.
|
||||
|
@ -38,13 +38,14 @@ class AttributeList {
|
||||
ActionBase::ExprTy **Args;
|
||||
unsigned NumArgs;
|
||||
AttributeList *Next;
|
||||
bool DeclspecAttribute;
|
||||
AttributeList(const AttributeList &); // DO NOT IMPLEMENT
|
||||
void operator=(const AttributeList &); // DO NOT IMPLEMENT
|
||||
public:
|
||||
AttributeList(IdentifierInfo *AttrName, SourceLocation AttrLoc,
|
||||
IdentifierInfo *ParmName, SourceLocation ParmLoc,
|
||||
ActionBase::ExprTy **args, unsigned numargs,
|
||||
AttributeList *Next);
|
||||
AttributeList *Next, bool declspec = false);
|
||||
~AttributeList();
|
||||
|
||||
enum Kind { // Please keep this list alphabetized.
|
||||
@ -103,6 +104,7 @@ class AttributeList {
|
||||
IdentifierInfo *getName() const { return AttrName; }
|
||||
SourceLocation getLoc() const { return AttrLoc; }
|
||||
IdentifierInfo *getParameterName() const { return ParmName; }
|
||||
bool isDeclspecAttribute() const { return DeclspecAttribute; }
|
||||
|
||||
Kind getKind() const { return getKind(getName()); }
|
||||
static Kind getKind(const IdentifierInfo *Name);
|
||||
|
@ -1064,7 +1064,7 @@ class Parser {
|
||||
// EndLoc, if non-NULL, is filled with the location of the last token of
|
||||
// the attribute list.
|
||||
AttributeList *ParseAttributes(SourceLocation *EndLoc = 0);
|
||||
void FuzzyParseMicrosoftDeclSpec();
|
||||
AttributeList *ParseMicrosoftDeclSpec();
|
||||
void ParseTypeofSpecifier(DeclSpec &DS);
|
||||
|
||||
/// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to
|
||||
|
@ -2838,30 +2838,6 @@ QualType::GCAttrTypes ASTContext::getObjCGCAttrKind(const QualType &Ty) const {
|
||||
// Type Compatibility Testing
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// typesAreBlockCompatible - This routine is called when comparing two
|
||||
/// block types. Types must be strictly compatible here. For example,
|
||||
/// C unfortunately doesn't produce an error for the following:
|
||||
///
|
||||
/// int (*emptyArgFunc)();
|
||||
/// int (*intArgList)(int) = emptyArgFunc;
|
||||
///
|
||||
/// For blocks, we will produce an error for the following (similar to C++):
|
||||
///
|
||||
/// int (^emptyArgBlock)();
|
||||
/// int (^intArgBlock)(int) = emptyArgBlock;
|
||||
///
|
||||
/// FIXME: When the dust settles on this integration, fold this into mergeTypes.
|
||||
///
|
||||
bool ASTContext::typesAreBlockCompatible(QualType lhs, QualType rhs) {
|
||||
const FunctionType *lbase = lhs->getAsFunctionType();
|
||||
const FunctionType *rbase = rhs->getAsFunctionType();
|
||||
const FunctionProtoType *lproto = dyn_cast<FunctionProtoType>(lbase);
|
||||
const FunctionProtoType *rproto = dyn_cast<FunctionProtoType>(rbase);
|
||||
if (lproto && rproto == 0)
|
||||
return false;
|
||||
return !mergeTypes(lhs, rhs).isNull();
|
||||
}
|
||||
|
||||
/// areCompatVectorTypes - Return true if the two specified vector types are
|
||||
/// compatible.
|
||||
static bool areCompatVectorTypes(const VectorType *LHS,
|
||||
|
@ -1556,6 +1556,22 @@ ObjCMessageExpr::ObjCMessageExpr(Expr *receiver, Selector selInfo,
|
||||
RBracloc = RBrac;
|
||||
}
|
||||
|
||||
ObjCStringLiteral* ObjCStringLiteral::Clone(ASTContext &C) const {
|
||||
// Clone the string literal.
|
||||
StringLiteral *NewString =
|
||||
String ? cast<StringLiteral>(String)->Clone(C) : 0;
|
||||
|
||||
return new (C) ObjCStringLiteral(NewString, getType(), AtLoc);
|
||||
}
|
||||
|
||||
ObjCSelectorExpr *ObjCSelectorExpr::Clone(ASTContext &C) const {
|
||||
return new (C) ObjCSelectorExpr(getType(), SelName, AtLoc, RParenLoc);
|
||||
}
|
||||
|
||||
ObjCProtocolExpr *ObjCProtocolExpr::Clone(ASTContext &C) const {
|
||||
return new (C) ObjCProtocolExpr(getType(), Protocol, AtLoc, RParenLoc);
|
||||
}
|
||||
|
||||
// constructor for class messages.
|
||||
// FIXME: clsName should be typed to ObjCInterfaceType
|
||||
ObjCMessageExpr::ObjCMessageExpr(IdentifierInfo *clsName, Selector selInfo,
|
||||
|
@ -347,9 +347,6 @@ FileID SourceManager::createFileID(const ContentCache *File,
|
||||
SrcMgr::CharacteristicKind FileCharacter,
|
||||
unsigned PreallocatedID,
|
||||
unsigned Offset) {
|
||||
SLocEntry NewEntry = SLocEntry::get(NextOffset,
|
||||
FileInfo::get(IncludePos, File,
|
||||
FileCharacter));
|
||||
if (PreallocatedID) {
|
||||
// If we're filling in a preallocated ID, just load in the file
|
||||
// entry and return.
|
||||
|
@ -244,6 +244,11 @@ static void GetDarwinLanguageOptions(LangOptions &Opts,
|
||||
Opts.ObjCNonFragileABI = 1;
|
||||
}
|
||||
|
||||
/// GetWindowsLanguageOptions - Set the default language options for Windows.
|
||||
static void GetWindowsLanguageOptions(LangOptions &Opts,
|
||||
const char *Triple) {
|
||||
Opts.Microsoft = true;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Specific target implementations.
|
||||
@ -924,9 +929,8 @@ class WindowsX86_32TargetInfo : public X86_32TargetInfo {
|
||||
WindowsX86_32TargetInfo(const std::string& triple)
|
||||
: X86_32TargetInfo(triple) {
|
||||
TLSSupported = false;
|
||||
// FIXME: Fix wchar_t.
|
||||
// FIXME: We should probably enable -fms-extensions by default for
|
||||
// this target.
|
||||
WCharType = SignedShort;
|
||||
WCharWidth = WCharAlign = 16;
|
||||
}
|
||||
virtual void getTargetDefines(const LangOptions &Opts,
|
||||
std::vector<char> &Defines) const {
|
||||
@ -938,6 +942,11 @@ class WindowsX86_32TargetInfo : public X86_32TargetInfo {
|
||||
Define(Defines, "_X86_");
|
||||
Define(Defines, "__MSVCRT__");
|
||||
}
|
||||
|
||||
virtual void getDefaultLangOptions(LangOptions &Opts) {
|
||||
X86_32TargetInfo::getDefaultLangOptions(Opts);
|
||||
GetWindowsLanguageOptions(Opts, getTargetTriple());
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
|
@ -782,29 +782,6 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
|
||||
Ops[0] = Builder.CreateBitCast(Ops[0], PtrTy);
|
||||
return Builder.CreateStore(Ops[1], Ops[0]);
|
||||
}
|
||||
case X86::BI__builtin_ia32_loadlv4si: {
|
||||
// load i64
|
||||
const llvm::Type *EltTy = llvm::Type::Int64Ty;
|
||||
llvm::Type *PtrTy = llvm::PointerType::getUnqual(EltTy);
|
||||
Ops[0] = Builder.CreateBitCast(Ops[0], PtrTy);
|
||||
Ops[0] = Builder.CreateLoad(Ops[0], "load");
|
||||
|
||||
// scalar to vector: insert i64 into 2 x i64 undef
|
||||
llvm::Type *VecTy = llvm::VectorType::get(EltTy, 2);
|
||||
llvm::Value *Zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
|
||||
Ops[0] = Builder.CreateInsertElement(llvm::UndefValue::get(VecTy),
|
||||
Ops[0], Zero, "s2v");
|
||||
|
||||
// shuffle into zero vector.
|
||||
std::vector<llvm::Constant *>Elts;
|
||||
Elts.resize(2, llvm::ConstantInt::get(EltTy, 0));
|
||||
llvm::Value *ZV = ConstantVector::get(Elts);
|
||||
Ops[0] = EmitShuffleVector(ZV, Ops[0], 2, 1, "loadl");
|
||||
|
||||
// bitcast to result.
|
||||
return Builder.CreateBitCast(Ops[0],
|
||||
llvm::VectorType::get(llvm::Type::Int32Ty, 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -310,7 +310,6 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
|
||||
// Filter out some microsoft extensions when trying to parse in ms-compat
|
||||
// mode.
|
||||
if (LangOpts.Microsoft) {
|
||||
DefineBuiltinMacro(Buf, "_cdecl=__cdecl");
|
||||
DefineBuiltinMacro(Buf, "__int8=__INT8_TYPE__");
|
||||
DefineBuiltinMacro(Buf, "__int16=__INT16_TYPE__");
|
||||
DefineBuiltinMacro(Buf, "__int32=__INT32_TYPE__");
|
||||
|
@ -1011,9 +1011,7 @@ Stmt *RewriteBlocks::RewriteFunctionBody(Stmt *S) {
|
||||
CI != E; ++CI)
|
||||
if (*CI) {
|
||||
if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
|
||||
Stmt *newStmt = RewriteFunctionBody(CBE->getBody());
|
||||
if (newStmt)
|
||||
*CI = newStmt;
|
||||
RewriteFunctionBody(CBE->getBody());
|
||||
|
||||
// We've just rewritten the block body in place.
|
||||
// Now we snarf the rewritten text and stash it away for later use.
|
||||
@ -1023,9 +1021,7 @@ Stmt *RewriteBlocks::RewriteFunctionBody(Stmt *S) {
|
||||
// Do the rewrite, using S.size() which contains the rewritten size.
|
||||
ReplaceText(CBE->getLocStart(), S.size(), Init.c_str(), Init.size());
|
||||
} else {
|
||||
Stmt *newStmt = RewriteFunctionBody(*CI);
|
||||
if (newStmt)
|
||||
*CI = newStmt;
|
||||
RewriteFunctionBody(*CI);
|
||||
}
|
||||
}
|
||||
// Handle specific things.
|
||||
|
@ -1020,7 +1020,7 @@ _mm_loadu_si128(__m128i const *p)
|
||||
static inline __m128i __attribute__((__always_inline__, __nodebug__))
|
||||
_mm_loadl_epi64(__m128i const *p)
|
||||
{
|
||||
return (__m128i)__builtin_ia32_loadlv4si((__v2si *)p);
|
||||
return (__m128i) { *(long long*)p, 0};
|
||||
}
|
||||
|
||||
static inline __m128i __attribute__((__always_inline__, __nodebug__))
|
||||
|
@ -18,9 +18,9 @@ using namespace clang;
|
||||
AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc,
|
||||
IdentifierInfo *pName, SourceLocation pLoc,
|
||||
ActionBase::ExprTy **ExprList, unsigned numArgs,
|
||||
AttributeList *n)
|
||||
AttributeList *n, bool declspec)
|
||||
: AttrName(aName), AttrLoc(aLoc), ParmName(pName), ParmLoc(pLoc),
|
||||
NumArgs(numArgs), Next(n) {
|
||||
NumArgs(numArgs), Next(n), DeclspecAttribute(declspec) {
|
||||
|
||||
if (numArgs == 0)
|
||||
Args = 0;
|
||||
|
@ -200,18 +200,50 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) {
|
||||
return CurrAttr;
|
||||
}
|
||||
|
||||
/// FuzzyParseMicrosoftDeclSpec. When -fms-extensions is enabled, this
|
||||
/// routine is called to skip/ignore tokens that comprise the MS declspec.
|
||||
void Parser::FuzzyParseMicrosoftDeclSpec() {
|
||||
/// ParseMicrosoftDeclSpec - Parse an __declspec construct
|
||||
///
|
||||
/// [MS] decl-specifier:
|
||||
/// __declspec ( extended-decl-modifier-seq )
|
||||
///
|
||||
/// [MS] extended-decl-modifier-seq:
|
||||
/// extended-decl-modifier[opt]
|
||||
/// extended-decl-modifier extended-decl-modifier-seq
|
||||
|
||||
AttributeList* Parser::ParseMicrosoftDeclSpec() {
|
||||
assert(Tok.is(tok::kw___declspec) && "Not a declspec!");
|
||||
|
||||
AttributeList *CurrAttr = 0;
|
||||
ConsumeToken();
|
||||
if (Tok.is(tok::l_paren)) {
|
||||
unsigned short savedParenCount = ParenCount;
|
||||
do {
|
||||
ConsumeAnyToken();
|
||||
} while (ParenCount > savedParenCount && Tok.isNot(tok::eof));
|
||||
}
|
||||
return;
|
||||
if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
|
||||
"declspec")) {
|
||||
SkipUntil(tok::r_paren, true); // skip until ) or ;
|
||||
return CurrAttr;
|
||||
}
|
||||
while (Tok.is(tok::identifier) || Tok.is(tok::kw_restrict)) {
|
||||
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
|
||||
SourceLocation AttrNameLoc = ConsumeToken();
|
||||
if (Tok.is(tok::l_paren)) {
|
||||
ConsumeParen();
|
||||
// FIXME: This doesn't parse __declspec(property(get=get_func_name))
|
||||
// correctly.
|
||||
OwningExprResult ArgExpr(ParseAssignmentExpression());
|
||||
if (!ArgExpr.isInvalid()) {
|
||||
ExprTy* ExprList = ArgExpr.take();
|
||||
CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
|
||||
SourceLocation(), &ExprList, 1,
|
||||
CurrAttr, true);
|
||||
}
|
||||
if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
|
||||
SkipUntil(tok::r_paren, false);
|
||||
} else {
|
||||
CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, SourceLocation(),
|
||||
0, 0, CurrAttr, true);
|
||||
}
|
||||
}
|
||||
if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
|
||||
SkipUntil(tok::r_paren, false);
|
||||
// FIXME: Return the attributes once we have some Sema support!
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// ParseDeclaration - Parse a full 'declaration', which consists of
|
||||
@ -809,7 +841,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
||||
case tok::kw___declspec:
|
||||
if (!PP.getLangOptions().Microsoft)
|
||||
goto DoneWithDeclSpec;
|
||||
FuzzyParseMicrosoftDeclSpec();
|
||||
DS.AddAttributes(ParseMicrosoftDeclSpec());
|
||||
continue;
|
||||
|
||||
// Microsoft single token adornments.
|
||||
|
@ -410,7 +410,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
|
||||
|
||||
// If declspecs exist after tag, parse them.
|
||||
if (Tok.is(tok::kw___declspec) && PP.getLangOptions().Microsoft)
|
||||
FuzzyParseMicrosoftDeclSpec();
|
||||
// FIXME: Need to do something with the attributes!
|
||||
ParseMicrosoftDeclSpec();
|
||||
|
||||
// Parse the (optional) nested-name-specifier.
|
||||
CXXScopeSpec SS;
|
||||
|
@ -1696,6 +1696,10 @@ class Sema : public Action {
|
||||
virtual ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
|
||||
ExprTy **Strings,
|
||||
unsigned NumStrings);
|
||||
|
||||
Expr *BuildObjCEncodeExpression(SourceLocation AtLoc,
|
||||
QualType EncodedType,
|
||||
SourceLocation RParenLoc);
|
||||
virtual ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,
|
||||
SourceLocation EncodeLoc,
|
||||
SourceLocation LParenLoc,
|
||||
|
@ -3003,8 +3003,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
|
||||
compositeType = Context.getObjCIdType();
|
||||
} else if (LHSBPT || RHSBPT) {
|
||||
if (!sameKind
|
||||
|| !Context.typesAreBlockCompatible(lhptee.getUnqualifiedType(),
|
||||
rhptee.getUnqualifiedType()))
|
||||
|| !Context.typesAreCompatible(lhptee.getUnqualifiedType(),
|
||||
rhptee.getUnqualifiedType()))
|
||||
Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
|
||||
<< LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
|
||||
return QualType();
|
||||
@ -3218,7 +3218,7 @@ Sema::CheckBlockPointerTypesForAssignment(QualType lhsType,
|
||||
if (lhptee.getCVRQualifiers() != rhptee.getCVRQualifiers())
|
||||
ConvTy = CompatiblePointerDiscardsQualifiers;
|
||||
|
||||
if (!Context.typesAreBlockCompatible(lhptee, rhptee))
|
||||
if (!Context.typesAreCompatible(lhptee, rhptee))
|
||||
return IncompatibleBlockPointer;
|
||||
return ConvTy;
|
||||
}
|
||||
@ -3978,7 +3978,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
|
||||
QualType rpointee = rType->getAsBlockPointerType()->getPointeeType();
|
||||
|
||||
if (!LHSIsNull && !RHSIsNull &&
|
||||
!Context.typesAreBlockCompatible(lpointee, rpointee)) {
|
||||
!Context.typesAreCompatible(lpointee, rpointee)) {
|
||||
Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)
|
||||
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
|
||||
}
|
||||
@ -5220,7 +5220,7 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
|
||||
|
||||
QualType BlockTy;
|
||||
if (!BSI->hasPrototype)
|
||||
BlockTy = Context.getFunctionNoProtoType(RetTy);
|
||||
BlockTy = Context.getFunctionType(RetTy, 0, 0, false, 0);
|
||||
else
|
||||
BlockTy = Context.getFunctionType(RetTy, ArgTypes.data(), ArgTypes.size(),
|
||||
BSI->isVariadic, 0);
|
||||
|
@ -92,6 +92,29 @@ Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
|
||||
return new (Context) ObjCStringLiteral(S, Ty, AtLocs[0]);
|
||||
}
|
||||
|
||||
Expr *Sema::BuildObjCEncodeExpression(SourceLocation AtLoc,
|
||||
QualType EncodedType,
|
||||
SourceLocation RParenLoc) {
|
||||
QualType StrTy;
|
||||
if (EncodedType->isDependentType())
|
||||
StrTy = Context.DependentTy;
|
||||
else {
|
||||
std::string Str;
|
||||
Context.getObjCEncodingForType(EncodedType, Str);
|
||||
|
||||
// The type of @encode is the same as the type of the corresponding string,
|
||||
// which is an array type.
|
||||
StrTy = Context.CharTy;
|
||||
// A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
|
||||
if (getLangOptions().CPlusPlus)
|
||||
StrTy.addConst();
|
||||
StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Str.size()+1),
|
||||
ArrayType::Normal, 0);
|
||||
}
|
||||
|
||||
return new (Context) ObjCEncodeExpr(StrTy, EncodedType, AtLoc, RParenLoc);
|
||||
}
|
||||
|
||||
Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
|
||||
SourceLocation EncodeLoc,
|
||||
SourceLocation LParenLoc,
|
||||
@ -99,19 +122,7 @@ Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
|
||||
SourceLocation RParenLoc) {
|
||||
QualType EncodedType = QualType::getFromOpaquePtr(ty);
|
||||
|
||||
std::string Str;
|
||||
Context.getObjCEncodingForType(EncodedType, Str);
|
||||
|
||||
// The type of @encode is the same as the type of the corresponding string,
|
||||
// which is an array type.
|
||||
QualType StrTy = Context.CharTy;
|
||||
// A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
|
||||
if (getLangOptions().CPlusPlus)
|
||||
StrTy.addConst();
|
||||
StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Str.size()+1),
|
||||
ArrayType::Normal, 0);
|
||||
|
||||
return new (Context) ObjCEncodeExpr(StrTy, EncodedType, AtLoc, RParenLoc);
|
||||
return BuildObjCEncodeExpression(AtLoc, EncodedType, RParenLoc);
|
||||
}
|
||||
|
||||
Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
|
||||
|
@ -265,6 +265,37 @@ static bool DeduceTemplateArguments(ASTContext &Context, QualType Param,
|
||||
return false;
|
||||
}
|
||||
|
||||
case Type::FunctionProto: {
|
||||
const FunctionProtoType *FunctionProtoArg =
|
||||
dyn_cast<FunctionProtoType>(Arg);
|
||||
if (!FunctionProtoArg)
|
||||
return false;
|
||||
|
||||
const FunctionProtoType *FunctionProtoParam =
|
||||
cast<FunctionProtoType>(Param);
|
||||
|
||||
// Check return types.
|
||||
if (!DeduceTemplateArguments(Context,
|
||||
FunctionProtoParam->getResultType(),
|
||||
FunctionProtoArg->getResultType(),
|
||||
Deduced))
|
||||
return false;
|
||||
|
||||
if (FunctionProtoParam->getNumArgs() != FunctionProtoArg->getNumArgs())
|
||||
return false;
|
||||
|
||||
for (unsigned I = 0, N = FunctionProtoParam->getNumArgs(); I != N; ++I) {
|
||||
// Check argument types.
|
||||
if (!DeduceTemplateArguments(Context,
|
||||
FunctionProtoParam->getArgType(I),
|
||||
FunctionProtoArg->getArgType(I),
|
||||
Deduced))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1216,15 +1216,22 @@ TemplateExprInstantiator::VisitCXXUnresolvedMemberExpr(
|
||||
// Objective-C Expressions
|
||||
//----------------------------------------------------------------------------
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitObjCStringLiteral(ObjCStringLiteral *E) {
|
||||
assert(false && "FIXME: Template instantiations for ObjC expressions");
|
||||
return SemaRef.ExprError();
|
||||
TemplateExprInstantiator::VisitObjCStringLiteral(ObjCStringLiteral *E) {
|
||||
return SemaRef.Owned(E->Clone(SemaRef.Context));
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
|
||||
assert(false && "FIXME: Template instantiations for ObjC expressions");
|
||||
return SemaRef.ExprError();
|
||||
TemplateExprInstantiator::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
|
||||
QualType EncodedType = SemaRef.InstantiateType(E->getEncodedType(),
|
||||
TemplateArgs,
|
||||
/*FIXME:*/E->getAtLoc(),
|
||||
DeclarationName());
|
||||
if (EncodedType.isNull())
|
||||
return SemaRef.ExprError();
|
||||
|
||||
return SemaRef.Owned(SemaRef.BuildObjCEncodeExpression(E->getAtLoc(),
|
||||
EncodedType,
|
||||
E->getRParenLoc()));
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
@ -1235,14 +1242,12 @@ TemplateExprInstantiator::VisitObjCMessageExpr(ObjCMessageExpr *E) {
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
|
||||
assert(false && "FIXME: Template instantiations for ObjC expressions");
|
||||
return SemaRef.ExprError();
|
||||
return SemaRef.Owned(E->Clone(SemaRef.Context));
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
|
||||
assert(false && "FIXME: Template instantiations for ObjC expressions");
|
||||
return SemaRef.ExprError();
|
||||
return SemaRef.Owned(E->Clone(SemaRef.Context));
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
|
@ -325,14 +325,9 @@ void f0() {
|
||||
tmp_V8s = __builtin_ia32_pmaddwd128(tmp_V8s, tmp_V8s);
|
||||
(void) __builtin_ia32_monitor(tmp_vp, tmp_Ui, tmp_Ui);
|
||||
(void) __builtin_ia32_mwait(tmp_Ui, tmp_Ui);
|
||||
#ifdef USE_ALL
|
||||
tmp_V4f = __builtin_ia32_movshdup(tmp_V4f);
|
||||
tmp_V4f = __builtin_ia32_movsldup(tmp_V4f);
|
||||
#endif
|
||||
tmp_V16c = __builtin_ia32_lddqu(tmp_cCp);
|
||||
tmp_V2LLi = __builtin_ia32_palignr128(tmp_V2LLi, tmp_V2LLi, imm_i);
|
||||
tmp_V1LLi = __builtin_ia32_palignr(tmp_V1LLi, tmp_V1LLi, imm_i);
|
||||
tmp_V4i = __builtin_ia32_loadlv4si(tmp_V2ip);
|
||||
(void) __builtin_ia32_storelv4si(tmp_V2ip, tmp_V2LLi);
|
||||
#ifdef USE_SSE4
|
||||
tmp_V16c = __builtin_ia32_pblendvb128(tmp_V16c, tmp_V16c, tmp_V16c);
|
||||
|
@ -18,7 +18,7 @@ void test() {
|
||||
^{return 1;}();
|
||||
^{return 2;}(arg); // expected-error {{too many arguments to block call}}
|
||||
^(void){return 3;}(1); // expected-error {{too many arguments to block call}}
|
||||
^(){return 4;}(arg); // C style (...), ok.
|
||||
^(){return 4;}(arg); // expected-error {{too many arguments to block call}}
|
||||
^(int x, ...){return 5;}(arg, arg); // Explicit varargs, ok.
|
||||
}
|
||||
|
||||
|
@ -7,10 +7,10 @@ int main() {
|
||||
int (*FPL) (int) = FP; // C doesn't consider this an error.
|
||||
|
||||
// For Blocks, the ASTContext::typesAreBlockCompatible() makes sure this is an error.
|
||||
int (^PFR) (int) = IFP; // expected-error {{incompatible block pointer types initializing 'int (^)()', expected 'int (^)(int)'}}
|
||||
int (^PFR) (int) = IFP; // OK
|
||||
PFR = II; // OK
|
||||
|
||||
int (^IFP) () = PFR;
|
||||
int (^IFP) () = PFR; // OK
|
||||
|
||||
|
||||
const int (^CIC) () = IFP; // expected-error {{incompatible block pointer types initializing 'int (^)()', expected 'int const (^)()'}}
|
||||
|
@ -10,7 +10,7 @@ int test1() {
|
||||
if (PFR == II) // OK
|
||||
donotwarn();
|
||||
|
||||
if (PFR == IFP) // expected-error {{comparison of distinct block types}}
|
||||
if (PFR == IFP) // OK
|
||||
donotwarn();
|
||||
|
||||
if (PFR == (int (^) (int))IFP) // OK
|
||||
@ -25,7 +25,7 @@ int test1() {
|
||||
if (!PFR) // OK
|
||||
donotwarn();
|
||||
|
||||
return PFR != IFP; // expected-error {{comparison of distinct block types}}
|
||||
return PFR != IFP; // OK
|
||||
}
|
||||
|
||||
int test2(double (^S)()) {
|
||||
@ -165,7 +165,7 @@ void test17() {
|
||||
|
||||
f(1 ? bp : vp);
|
||||
f(1 ? vp : bp);
|
||||
f(1 ? bp : bp1); // expected-error {{incompatible operand types ('void (^)(int)' and 'void (^)()')}}
|
||||
f(1 ? bp : bp1);
|
||||
(void)(bp > rp); // expected-error {{invalid operands}}
|
||||
(void)(bp > 0); // expected-error {{invalid operands}}
|
||||
(void)(bp > bp); // expected-error {{invalid operands}}
|
||||
|
@ -28,7 +28,7 @@ void foo5(id (^objectCreationBlock)(int)) {
|
||||
|
||||
void bar6(id(^)(int));
|
||||
void foo6(id (^objectCreationBlock)()) {
|
||||
return bar6(objectCreationBlock); // expected-error {{incompatible block pointer types passing 'id (^)()', expected 'id (^)(int)'}}
|
||||
return bar6(objectCreationBlock);
|
||||
}
|
||||
|
||||
void foo7(id (^x)(int)) {
|
||||
|
47
test/SemaTemplate/instantiate-objc-1.mm
Normal file
47
test/SemaTemplate/instantiate-objc-1.mm
Normal file
@ -0,0 +1,47 @@
|
||||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
|
||||
// Obj-C string literal expressions
|
||||
template <typename T> struct StringTest {
|
||||
void f() {
|
||||
(void)@"Hello";
|
||||
}
|
||||
};
|
||||
|
||||
template struct StringTest<int>;
|
||||
template struct StringTest<double>;
|
||||
|
||||
// @selector expressions
|
||||
template <typename T> struct SelectorTest {
|
||||
SEL f() {
|
||||
return @selector(multiple:arguments:);
|
||||
}
|
||||
SEL f2() {
|
||||
return @selector(multiple:arguments:);
|
||||
}
|
||||
};
|
||||
|
||||
template struct SelectorTest<int>;
|
||||
template struct SelectorTest<double>;
|
||||
|
||||
// @protocol expressions
|
||||
@protocol P
|
||||
@end
|
||||
|
||||
template <typename T> struct ProtocolTest {
|
||||
void f() {
|
||||
(void)@protocol(P);
|
||||
}
|
||||
};
|
||||
|
||||
template struct ProtocolTest<int>;
|
||||
template struct ProtocolTest<double>;
|
||||
|
||||
// @encode expressions
|
||||
template <typename T> struct EncodeTest {
|
||||
static const char *encode(T t) {
|
||||
return @encode(T);
|
||||
}
|
||||
};
|
||||
|
||||
template struct EncodeTest<int>;
|
||||
template struct EncodeTest<double>;
|
@ -102,3 +102,35 @@ struct get_array_size<T[N]> {
|
||||
};
|
||||
|
||||
int array_size0[get_array_size<int[12]>::value == 12? 1 : -1];
|
||||
|
||||
template<typename T>
|
||||
struct is_unary_function {
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct is_unary_function<T (*)(U)> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
int is_unary_function0[is_unary_function<int>::value ? -1 : 1];
|
||||
int is_unary_function1[is_unary_function<int (*)()>::value ? -1 : 1];
|
||||
int is_unary_function2[is_unary_function<int (*)(int, bool)>::value ? -1 : 1];
|
||||
int is_unary_function3[is_unary_function<int (*)(bool)>::value ? 1 : -1];
|
||||
int is_unary_function4[is_unary_function<int (*)(int)>::value ? 1 : -1];
|
||||
|
||||
template<typename T>
|
||||
struct is_unary_function_with_same_return_type_as_argument_type {
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_unary_function_with_same_return_type_as_argument_type<T (*)(T)> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
int is_unary_function5[is_unary_function_with_same_return_type_as_argument_type<int>::value ? -1 : 1];
|
||||
int is_unary_function6[is_unary_function_with_same_return_type_as_argument_type<int (*)()>::value ? -1 : 1];
|
||||
int is_unary_function7[is_unary_function_with_same_return_type_as_argument_type<int (*)(int, bool)>::value ? -1 : 1];
|
||||
int is_unary_function8[is_unary_function_with_same_return_type_as_argument_type<int (*)(bool)>::value ? -1 : 1];
|
||||
int is_unary_function9[is_unary_function_with_same_return_type_as_argument_type<int (*)(int)>::value ? 1 : -1];
|
||||
|
@ -808,7 +808,8 @@ static void InitializeLanguageStandard(LangOptions &Options, LangKind LK,
|
||||
|
||||
if (PascalStrings.getPosition())
|
||||
Options.PascalStrings = PascalStrings;
|
||||
Options.Microsoft = MSExtensions;
|
||||
if (MSExtensions.getPosition())
|
||||
Options.Microsoft = MSExtensions;
|
||||
Options.WritableStrings = WritableStrings;
|
||||
if (NoLaxVectorConversions.getPosition())
|
||||
Options.LaxVectorConversions = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user