Update clang to r100285.

This commit is contained in:
Roman Divacky 2010-04-03 07:51:34 +00:00
parent 11d2b2d2bb
commit 2c56c396ce
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=206125
37 changed files with 529 additions and 321 deletions

View File

@ -624,17 +624,23 @@ class ObjCIvarDecl : public FieldDecl {
};
private:
ObjCIvarDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation L, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW)
: FieldDecl(ObjCIvar, DC, L, Id, T, TInfo, BW, /*Mutable=*/false),
DeclAccess(ac) {}
public:
static ObjCIvarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T,
static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC,
SourceLocation L, IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo,
AccessControl ac, Expr *BW = NULL);
/// \brief Return the class interface that this ivar is logically contained
/// in; this is either the interface where the ivar was declared, or the
/// interface the ivar is conceptually a part of in the case of synthesized
/// ivars.
const ObjCInterfaceDecl *getContainingInterface() const;
void setAccessControl(AccessControl ac) { DeclAccess = ac; }
AccessControl getAccessControl() const { return AccessControl(DeclAccess); }

View File

@ -322,6 +322,15 @@ class Expr : public Stmt {
/// the expression is a default argument.
bool isDefaultArgument() const;
/// \brief Determine whether this expression directly creates a
/// temporary object (of class type).
bool isTemporaryObject() const { return getTemporaryObject() != 0; }
/// \brief If this expression directly creates a temporary object of
/// class type, return the expression that actually constructs that
/// temporary object.
const Expr *getTemporaryObject() const;
const Expr* IgnoreParens() const {
return const_cast<Expr*>(this)->IgnoreParens();
}

View File

@ -182,6 +182,8 @@ def err_unexected_colon_in_nested_name_spec : Error<
"unexpected ':' in nested name specifier">;
/// Objective-C parser diagnostics
def err_expected_minus_or_plus : Error<
"method type specifier must start with '-' or '+'">;
def err_objc_no_attributes_on_category : Error<
"attributes may not be specified on a category">;
def err_objc_missing_end : Error<"missing @end">;

View File

@ -256,6 +256,10 @@ def warn_property_attribute : Warning<
def warn_property_types_are_incompatible : Warning<
"property type %0 is incompatible with type %1 inherited from %2">;
def err_undef_interface : Error<"cannot find interface declaration for %0">;
def err_class_extension_after_impl : Error<
"cannot declare class extension for %0 after class implementation">;
def note_implementation_declared : Note<
"class implementation is declared here">;
def warn_dup_category_def : Warning<
"duplicate definition of category %1 on interface %0">;
def err_conflicting_super_class : Error<"conflicting super class name %0">;

View File

@ -431,6 +431,7 @@ def mno_sse4_1 : Flag<"-mno-sse4.1">, Group<m_x86_Features_Group>;
def mno_sse4_2 : Flag<"-mno-sse4.2">, Group<m_x86_Features_Group>;
def mno_sse : Flag<"-mno-sse">, Group<m_x86_Features_Group>;
def mno_ssse3 : Flag<"-mno-ssse3">, Group<m_x86_Features_Group>;
def mno_aes : Flag<"-mno-aes">, Group<m_x86_Features_Group>;
def mno_thumb : Flag<"-mno-thumb">, Group<m_Group>;
def marm : Flag<"-marm">, Alias<mno_thumb>;
@ -447,6 +448,7 @@ def msse4_1 : Flag<"-msse4.1">, Group<m_x86_Features_Group>;
def msse4_2 : Flag<"-msse4.2">, Group<m_x86_Features_Group>;
def msse : Flag<"-msse">, Group<m_x86_Features_Group>;
def mssse3 : Flag<"-mssse3">, Group<m_x86_Features_Group>;
def maes : Flag<"-maes">, Group<m_x86_Features_Group>;
def mthumb : Flag<"-mthumb">, Group<m_Group>;
def mtune_EQ : Joined<"-mtune=">, Group<m_Group>;
def multi__module : Flag<"-multi_module">;

View File

@ -2013,7 +2013,8 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
if (!BitWidth && D->getBitWidth())
return 0;
ObjCIvarDecl *ToIvar = ObjCIvarDecl::Create(Importer.getToContext(), DC,
ObjCIvarDecl *ToIvar = ObjCIvarDecl::Create(Importer.getToContext(),
cast<ObjCContainerDecl>(DC),
Loc, Name.getAsIdentifierInfo(),
T, TInfo, D->getAccessControl(),
BitWidth);

View File

@ -561,14 +561,53 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
// ObjCIvarDecl
//===----------------------------------------------------------------------===//
ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, DeclContext *DC,
ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
SourceLocation L, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo,
AccessControl ac, Expr *BW) {
if (DC) {
// Ivar's can only appear in interfaces, implementations (via synthesized
// properties), and class extensions (via direct declaration, or synthesized
// properties).
//
// FIXME: This should really be asserting this:
// (isa<ObjCCategoryDecl>(DC) &&
// cast<ObjCCategoryDecl>(DC)->IsClassExtension()))
// but unfortunately we sometimes place ivars into non-class extension
// categories on error. This breaks an AST invariant, and should not be
// fixed.
assert((isa<ObjCInterfaceDecl>(DC) || isa<ObjCImplementationDecl>(DC) ||
isa<ObjCCategoryDecl>(DC)) &&
"Invalid ivar decl context!");
}
return new (C) ObjCIvarDecl(DC, L, Id, T, TInfo, ac, BW);
}
const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const {
const ObjCContainerDecl *DC = cast<ObjCContainerDecl>(getDeclContext());
switch (DC->getKind()) {
default:
case ObjCCategoryImpl:
case ObjCProtocol:
assert(0 && "invalid ivar container!");
return 0;
// Ivars can only appear in class extension categories.
case ObjCCategory: {
const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(DC);
assert(CD->IsClassExtension() && "invalid container for ivar!");
return CD->getClassInterface();
}
case ObjCImplementation:
return cast<ObjCImplementationDecl>(DC)->getClassInterface();
case ObjCInterface:
return cast<ObjCInterfaceDecl>(DC);
}
}
//===----------------------------------------------------------------------===//
// ObjCAtDefsFieldDecl

View File

@ -1476,6 +1476,71 @@ bool Expr::isDefaultArgument() const {
return isa<CXXDefaultArgExpr>(E);
}
/// \brief Skip over any no-op casts and any temporary-binding
/// expressions.
static const Expr *skipTemporaryBindingsAndNoOpCasts(const Expr *E) {
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
if (ICE->getCastKind() == CastExpr::CK_NoOp)
E = ICE->getSubExpr();
else
break;
}
while (const CXXBindTemporaryExpr *BE = dyn_cast<CXXBindTemporaryExpr>(E))
E = BE->getSubExpr();
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
if (ICE->getCastKind() == CastExpr::CK_NoOp)
E = ICE->getSubExpr();
else
break;
}
return E;
}
const Expr *Expr::getTemporaryObject() const {
const Expr *E = skipTemporaryBindingsAndNoOpCasts(this);
// A cast can produce a temporary object. The object's construction
// is represented as a CXXConstructExpr.
if (const CastExpr *Cast = dyn_cast<CastExpr>(E)) {
// Only user-defined and constructor conversions can produce
// temporary objects.
if (Cast->getCastKind() != CastExpr::CK_ConstructorConversion &&
Cast->getCastKind() != CastExpr::CK_UserDefinedConversion)
return 0;
// Strip off temporary bindings and no-op casts.
const Expr *Sub = skipTemporaryBindingsAndNoOpCasts(Cast->getSubExpr());
// If this is a constructor conversion, see if we have an object
// construction.
if (Cast->getCastKind() == CastExpr::CK_ConstructorConversion)
return dyn_cast<CXXConstructExpr>(Sub);
// If this is a user-defined conversion, see if we have a call to
// a function that itself returns a temporary object.
if (Cast->getCastKind() == CastExpr::CK_UserDefinedConversion)
if (const CallExpr *CE = dyn_cast<CallExpr>(Sub))
if (CE->getCallReturnType()->isRecordType())
return CE;
return 0;
}
// A call returning a class type returns a temporary.
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
if (CE->getCallReturnType()->isRecordType())
return CE;
return 0;
}
// Explicit temporary object constructors create temporaries.
return dyn_cast<CXXTemporaryObjectExpr>(E);
}
/// hasAnyTypeDependentArguments - Determines if any of the expressions
/// in Exprs is type-dependent.
bool Expr::hasAnyTypeDependentArguments(Expr** Exprs, unsigned NumExprs) {

View File

@ -765,9 +765,12 @@ class X86TargetInfo : public TargetInfo {
NoAMD3DNow, AMD3DNow, AMD3DNowAthlon
} AMD3DNowLevel;
bool HasAES;
public:
X86TargetInfo(const std::string& triple)
: TargetInfo(triple), SSELevel(NoMMXSSE), AMD3DNowLevel(NoAMD3DNow) {
: TargetInfo(triple), SSELevel(NoMMXSSE), AMD3DNowLevel(NoAMD3DNow),
HasAES(false) {
LongDoubleFormat = &llvm::APFloat::x87DoubleExtended;
}
virtual void getTargetBuiltins(const Builtin::Info *&Records,
@ -813,6 +816,7 @@ void X86TargetInfo::getDefaultFeatures(const std::string &CPU,
Features["ssse3"] = false;
Features["sse41"] = false;
Features["sse42"] = false;
Features["aes"] = false;
// LLVM does not currently recognize this.
// Features["sse4a"] = false;
@ -841,8 +845,10 @@ void X86TargetInfo::getDefaultFeatures(const std::string &CPU,
Features["sse42"] = false;
} else if (CPU == "atom")
setFeatureEnabled(Features, "sse3", true);
else if (CPU == "corei7")
else if (CPU == "corei7") {
setFeatureEnabled(Features, "sse4", true);
setFeatureEnabled(Features, "aes", true);
}
else if (CPU == "k6" || CPU == "winchip-c6")
setFeatureEnabled(Features, "mmx", true);
else if (CPU == "k6-2" || CPU == "k6-3" || CPU == "athlon" ||
@ -892,6 +898,8 @@ bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
Features["3dnowa"] = true;
else if (Name == "3dnowa")
Features["3dnow"] = Features["3dnowa"] = true;
else if (Name == "aes")
Features["aes"] = true;
} else {
if (Name == "mmx")
Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] =
@ -917,6 +925,8 @@ bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
Features["3dnow"] = Features["3dnowa"] = false;
else if (Name == "3dnowa")
Features["3dnowa"] = false;
else if (Name == "aes")
Features["aes"] = false;
}
return true;
@ -931,6 +941,11 @@ void X86TargetInfo::HandleTargetFeatures(std::vector<std::string> &Features) {
if (Features[i][0] == '-')
continue;
if (Features[i].substr(1) == "aes") {
HasAES = true;
continue;
}
assert(Features[i][0] == '+' && "Invalid target feature!");
X86SSEEnum Level = llvm::StringSwitch<X86SSEEnum>(Features[i].substr(1))
.Case("sse42", SSE42)
@ -969,6 +984,9 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
DefineStd(Builder, "i386", Opts);
}
if (HasAES)
Builder.defineMacro("__AES__");
// Target properties.
Builder.defineMacro("__LITTLE_ENDIAN__");

View File

@ -1390,9 +1390,9 @@ void CGDebugInfo::EmitStopPoint(llvm::Function *Fn, CGBuilderTy &Builder) {
PresumedLoc PLoc = SM.getPresumedLoc(CurLoc);
llvm::MDNode *Scope = RegionStack.back();
Builder.SetCurrentDebugLocation(llvm::NewDebugLoc::get(PLoc.getLine(),
PLoc.getColumn(),
Scope));
Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(PLoc.getLine(),
PLoc.getColumn(),
Scope));
}
/// EmitRegionStart- Constructs the debug code for entering a declarative
@ -1596,7 +1596,7 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertBlock());
llvm::MDNode *Scope = RegionStack.back();
Call->setDebugLoc(llvm::NewDebugLoc::get(Line, Column, Scope));
Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
}
/// EmitDeclare - Emit local variable declaration debug info.
@ -1660,7 +1660,7 @@ void CGDebugInfo::EmitDeclare(const BlockDeclRefExpr *BDRE, unsigned Tag,
DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertBlock());
llvm::MDNode *Scope = RegionStack.back();
Call->setDebugLoc(llvm::NewDebugLoc::get(Line, PLoc.getColumn(), Scope));
Call->setDebugLoc(llvm::DebugLoc::get(Line, PLoc.getColumn(), Scope));
}
void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,

View File

@ -307,23 +307,7 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,
// Code gen optimization to eliminate copy constructor and return
// its first argument instead.
if (getContext().getLangOptions().ElideConstructors && E->isElidable()) {
const Expr *Arg = E->getArg(0);
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
assert((ICE->getCastKind() == CastExpr::CK_NoOp ||
ICE->getCastKind() == CastExpr::CK_ConstructorConversion ||
ICE->getCastKind() == CastExpr::CK_UserDefinedConversion) &&
"Unknown implicit cast kind in constructor elision");
Arg = ICE->getSubExpr();
}
if (const CXXFunctionalCastExpr *FCE = dyn_cast<CXXFunctionalCastExpr>(Arg))
Arg = FCE->getSubExpr();
if (const CXXBindTemporaryExpr *BindExpr =
dyn_cast<CXXBindTemporaryExpr>(Arg))
Arg = BindExpr->getSubExpr();
const Expr *Arg = E->getArg(0)->getTemporaryObject();
EmitAggExpr(Arg, Dest, false);
return;
}

View File

@ -42,41 +42,15 @@ using namespace CodeGen;
// don't belong in CGObjCRuntime either so we will live with it for
// now.
/// FindIvarInterface - Find the interface containing the ivar.
///
/// FIXME: We shouldn't need to do this, the containing context should
/// be fixed.
static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context,
const ObjCInterfaceDecl *OID,
const ObjCIvarDecl *OIVD,
unsigned &Index) {
// FIXME: The index here is closely tied to how
// ASTContext::getObjCLayout is implemented. This should be fixed to
// get the information from the layout directly.
Index = 0;
llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
Context.ShallowCollectObjCIvars(OID, Ivars);
for (unsigned k = 0, e = Ivars.size(); k != e; ++k) {
if (OIVD == Ivars[k])
return OID;
++Index;
}
// Otherwise check in the super class.
if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
return FindIvarInterface(Context, Super, OIVD, Index);
return 0;
}
static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM,
const ObjCInterfaceDecl *OID,
const ObjCImplementationDecl *ID,
const ObjCIvarDecl *Ivar) {
unsigned Index;
const ObjCInterfaceDecl *Container =
FindIvarInterface(CGM.getContext(), OID, Ivar, Index);
assert(Container && "Unable to find ivar container");
const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
// FIXME: We should eliminate the need to have ObjCImplementationDecl passed
// in here; it should never be necessary because that should be the lexical
// decl context for the ivar.
// If we know have an implementation (and the ivar is in it) then
// look up in the implementation layout.
@ -85,6 +59,22 @@ static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM,
RL = &CGM.getContext().getASTObjCImplementationLayout(ID);
else
RL = &CGM.getContext().getASTObjCInterfaceLayout(Container);
// Compute field index.
//
// FIXME: The index here is closely tied to how ASTContext::getObjCLayout is
// implemented. This should be fixed to get the information from the layout
// directly.
unsigned Index = 0;
llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
CGM.getContext().ShallowCollectObjCIvars(Container, Ivars);
for (unsigned k = 0, e = Ivars.size(); k != e; ++k) {
if (Ivar == Ivars[k])
break;
++Index;
}
assert(Index != Ivars.size() && "Ivar is not inside container!");
return RL->getFieldOffset(Index);
}
@ -4727,14 +4717,10 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name,
/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
/// the given ivar.
llvm::GlobalVariable * CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(
const ObjCInterfaceDecl *ID,
const ObjCIvarDecl *Ivar) {
// FIXME: We shouldn't need to do this lookup.
unsigned Index;
const ObjCInterfaceDecl *Container =
FindIvarInterface(CGM.getContext(), ID, Ivar, Index);
assert(Container && "Unable to find ivar container!");
llvm::GlobalVariable *
CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
const ObjCIvarDecl *Ivar) {
const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
'.' + Ivar->getNameAsString();
llvm::GlobalVariable *IvarOffsetGV =
@ -4749,10 +4735,10 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(
return IvarOffsetGV;
}
llvm::Constant * CGObjCNonFragileABIMac::EmitIvarOffsetVar(
const ObjCInterfaceDecl *ID,
const ObjCIvarDecl *Ivar,
unsigned long int Offset) {
llvm::Constant *
CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
const ObjCIvarDecl *Ivar,
unsigned long int Offset) {
llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
Offset));

View File

@ -3146,11 +3146,16 @@ void CodeGenVTables::EmitVTableRelatedData(GlobalDecl GD) {
if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl())
return;
} else {
// If we have no key funcion and this is a explicit instantiation declaration,
// we will produce a vtable at the explicit instantiation. We don't need one
// here.
if (RDKind == clang::TSK_ExplicitInstantiationDeclaration)
return;
// If this is an explicit instantiation of a method, we don't need a vtable.
// Since we have no key function, we will emit the vtable when we see
// a use, and just defining a function is not an use.
if ((RDKind == TSK_ImplicitInstantiation ||
RDKind == TSK_ExplicitInstantiationDeclaration) &&
if (RDKind == TSK_ImplicitInstantiation &&
MDKind == TSK_ExplicitInstantiationDefinition)
return;
}

View File

@ -142,12 +142,11 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
// We have a class or category name - consume it.
IdentifierInfo *nameId = Tok.getIdentifierInfo();
SourceLocation nameLoc = ConsumeToken();
bool Err = false;
if (Tok.is(tok::l_paren)) { // we have a category.
SourceLocation lparenLoc = ConsumeParen();
SourceLocation categoryLoc, rparenLoc;
IdentifierInfo *categoryId = 0;
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCInterfaceCategory(CurScope, nameId);
ConsumeToken();
@ -157,7 +156,14 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
if (Tok.is(tok::identifier)) {
categoryId = Tok.getIdentifierInfo();
categoryLoc = ConsumeToken();
} else if (!getLang().ObjC2) {
}
else if (isKnownToBeTypeSpecifier(Tok)) {
// Fall thru after diagnosing for better error recovery.
Diag(Tok, diag::err_expected_minus_or_plus);
ConsumeToken();
Err = true;
}
else if (!getLang().ObjC2) {
Diag(Tok, diag::err_expected_ident); // missing category name.
return DeclPtrTy();
}
@ -167,33 +173,34 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
return DeclPtrTy();
}
rparenLoc = ConsumeParen();
// Next, we need to check for any protocol references.
SourceLocation LAngleLoc, EndProtoLoc;
llvm::SmallVector<DeclPtrTy, 8> ProtocolRefs;
llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
if (Tok.is(tok::less) &&
ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
if (!Err) {
// Next, we need to check for any protocol references.
SourceLocation LAngleLoc, EndProtoLoc;
llvm::SmallVector<DeclPtrTy, 8> ProtocolRefs;
llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
if (Tok.is(tok::less) &&
ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
LAngleLoc, EndProtoLoc))
return DeclPtrTy();
return DeclPtrTy();
if (attrList) // categories don't support attributes.
Diag(Tok, diag::err_objc_no_attributes_on_category);
if (attrList) // categories don't support attributes.
Diag(Tok, diag::err_objc_no_attributes_on_category);
DeclPtrTy CategoryType =
Actions.ActOnStartCategoryInterface(atLoc,
nameId, nameLoc,
categoryId, categoryLoc,
ProtocolRefs.data(),
ProtocolRefs.size(),
ProtocolLocs.data(),
EndProtoLoc);
if (Tok.is(tok::l_brace))
DeclPtrTy CategoryType =
Actions.ActOnStartCategoryInterface(atLoc,
nameId, nameLoc,
categoryId, categoryLoc,
ProtocolRefs.data(),
ProtocolRefs.size(),
ProtocolLocs.data(),
EndProtoLoc);
if (Tok.is(tok::l_brace))
ParseObjCClassInstanceVariables(CategoryType, tok::objc_private,
atLoc);
ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword);
return CategoryType;
ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword);
return CategoryType;
}
}
// Parse a class interface.
IdentifierInfo *superClassId = 0;
@ -235,7 +242,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, atLoc);
ParseObjCInterfaceDeclList(ClsType, tok::objc_interface);
return ClsType;
return Err ? DeclPtrTy() : ClsType;
}
/// The Objective-C property callback. This should be defined where
@ -328,7 +335,14 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
"", tok::semi);
continue;
}
if (Tok.is(tok::l_paren)) {
Diag(Tok, diag::err_expected_minus_or_plus);
DeclPtrTy methodPrototype = ParseObjCMethodDecl(Tok.getLocation(),
tok::minus,
interfaceDecl,
MethodImplKind);
continue;
}
// Ignore excess semicolons.
if (Tok.is(tok::semi)) {
ConsumeToken();

View File

@ -5740,17 +5740,15 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S,
Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility)
: ObjCIvarDecl::None;
// Must set ivar's DeclContext to its enclosing interface.
Decl *EnclosingDecl = IntfDecl.getAs<Decl>();
DeclContext *EnclosingContext;
ObjCContainerDecl *EnclosingDecl = IntfDecl.getAs<ObjCContainerDecl>();
ObjCContainerDecl *EnclosingContext;
if (ObjCImplementationDecl *IMPDecl =
dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
// Case of ivar declared in an implementation. Context is that of its class.
ObjCInterfaceDecl* IDecl = IMPDecl->getClassInterface();
assert(IDecl && "No class- ActOnIvar");
EnclosingContext = cast_or_null<DeclContext>(IDecl);
EnclosingContext = IMPDecl->getClassInterface();
assert(EnclosingContext && "Implementation has no class interface!");
} else
EnclosingContext = dyn_cast<DeclContext>(EnclosingDecl);
assert(EnclosingContext && "null DeclContext for ivar - ActOnIvar");
EnclosingContext = EnclosingDecl;
// Construct the decl.
ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context,

View File

@ -3965,33 +3965,21 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
bool BaseInitialization) {
bool Elidable = false;
// C++ [class.copy]p15:
// Whenever a temporary class object is copied using a copy constructor, and
// this object and the copy have the same cv-unqualified type, an
// implementation is permitted to treat the original and the copy as two
// different ways of referring to the same object and not perform a copy at
// all, even if the class copy constructor or destructor have side effects.
// FIXME: Is this enough?
if (Constructor->isCopyConstructor()) {
Expr *E = ((Expr **)ExprArgs.get())[0];
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
if (ICE->getCastKind() == CastExpr::CK_NoOp)
E = ICE->getSubExpr();
if (CXXFunctionalCastExpr *FCE = dyn_cast<CXXFunctionalCastExpr>(E))
E = FCE->getSubExpr();
while (CXXBindTemporaryExpr *BE = dyn_cast<CXXBindTemporaryExpr>(E))
E = BE->getSubExpr();
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
if (ICE->getCastKind() == CastExpr::CK_NoOp)
E = ICE->getSubExpr();
if (CallExpr *CE = dyn_cast<CallExpr>(E))
Elidable = !CE->getCallReturnType()->isReferenceType();
else if (isa<CXXTemporaryObjectExpr>(E))
Elidable = true;
else if (isa<CXXConstructExpr>(E))
Elidable = true;
// C++0x [class.copy]p34:
// When certain criteria are met, an implementation is allowed to
// omit the copy/move construction of a class object, even if the
// copy/move constructor and/or destructor for the object have
// side effects. [...]
// - when a temporary class object that has not been bound to a
// reference (12.2) would be copied/moved to a class object
// with the same cv-unqualified type, the copy/move operation
// can be omitted by constructing the temporary object
// directly into the target of the omitted copy/move
if (Constructor->isCopyConstructor() && ExprArgs.size() >= 1) {
Expr *SubExpr = ((Expr **)ExprArgs.get())[0];
Elidable = SubExpr->isTemporaryObject() &&
Context.hasSameUnqualifiedType(SubExpr->getType(),
Context.getTypeDeclType(Constructor->getParent()));
}
return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor,

View File

@ -431,6 +431,11 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
// Class extensions require a special treatment. Use an existing one.
// Note that 'getClassExtension()' can return NULL.
CDecl = IDecl->getClassExtension();
if (IDecl->getImplementation()) {
Diag(ClassLoc, diag::err_class_extension_after_impl) << ClassName;
Diag(IDecl->getImplementation()->getLocation(),
diag::note_implementation_declared);
}
}
if (!CDecl) {

View File

@ -1345,11 +1345,6 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
}
}
}
if (LangOpts.ObjCNonFragileABI2 && LookForIvars && Lookup.empty()) {
ObjCIvarDecl *Ivar = SynthesizeNewPropertyIvar(IFace, II);
if (Ivar)
return LookupInObjCMethod(Lookup, S, II, AllowBuiltinCreation);
}
// Sentinel value saying that we didn't do anything special.
return Owned((Expr*) 0);
}

View File

@ -2583,10 +2583,7 @@ static void TryConstructorInitialization(Sema &S,
Expr **Args, unsigned NumArgs,
QualType DestType,
InitializationSequence &Sequence) {
if (Kind.getKind() == InitializationKind::IK_Copy)
Sequence.setSequenceKind(InitializationSequence::UserDefinedConversion);
else
Sequence.setSequenceKind(InitializationSequence::ConstructorInitialization);
Sequence.setSequenceKind(InitializationSequence::ConstructorInitialization);
// Build the candidate set directly in the initialization sequence
// structure, so that it will persist if we fail.
@ -2597,7 +2594,7 @@ static void TryConstructorInitialization(Sema &S,
// explicit conversion operators.
bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct ||
Kind.getKind() == InitializationKind::IK_Value ||
Kind.getKind() == InitializationKind::IK_Default);
Kind.getKind() == InitializationKind::IK_Default);
// The type we're converting to is a class type. Enumerate its constructors
// to see if one is suitable.
@ -2661,14 +2658,10 @@ static void TryConstructorInitialization(Sema &S,
// Add the constructor initialization step. Any cv-qualification conversion is
// subsumed by the initialization.
if (Kind.getKind() == InitializationKind::IK_Copy) {
Sequence.AddUserConversionStep(Best->Function, Best->FoundDecl, DestType);
} else {
Sequence.AddConstructorInitializationStep(
Sequence.AddConstructorInitializationStep(
cast<CXXConstructorDecl>(Best->Function),
Best->FoundDecl.getAccess(),
DestType);
}
}
/// \brief Attempt value initialization (C++ [dcl.init]p7).
@ -3085,14 +3078,11 @@ getAssignmentAction(const InitializedEntity &Entity) {
return Sema::AA_Converting;
}
static bool shouldBindAsTemporary(const InitializedEntity &Entity,
bool IsCopy) {
static bool shouldBindAsTemporary(const InitializedEntity &Entity) {
switch (Entity.getKind()) {
case InitializedEntity::EK_Result:
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_Member:
return !IsCopy;
case InitializedEntity::EK_Result:
case InitializedEntity::EK_New:
case InitializedEntity::EK_Variable:
case InitializedEntity::EK_Base:
@ -3108,21 +3098,38 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity,
llvm_unreachable("missed an InitializedEntity kind?");
}
/// \brief If we need to perform an additional copy of the initialized object
/// for this kind of entity (e.g., the result of a function or an object being
/// thrown), make the copy.
static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
Sema::OwningExprResult CurInit) {
static Sema::OwningExprResult CopyObject(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
Sema::OwningExprResult CurInit) {
// Determine which class type we're copying.
Expr *CurInitExpr = (Expr *)CurInit.get();
CXXRecordDecl *Class = 0;
if (const RecordType *Record = CurInitExpr->getType()->getAs<RecordType>())
Class = cast<CXXRecordDecl>(Record->getDecl());
if (!Class)
return move(CurInit);
// C++0x [class.copy]p34:
// When certain criteria are met, an implementation is allowed to
// omit the copy/move construction of a class object, even if the
// copy/move constructor and/or destructor for the object have
// side effects. [...]
// - when a temporary class object that has not been bound to a
// reference (12.2) would be copied/moved to a class object
// with the same cv-unqualified type, the copy/move operation
// can be omitted by constructing the temporary object
// directly into the target of the omitted copy/move
//
// Note that the other three bullets are handled elsewhere. Copy
// elision for return statements and throw expressions are (FIXME:
// not yet) handled as part of constructor initialization, while
// copy elision for exception handlers is handled by the run-time.
bool Elidable = CurInitExpr->isTemporaryObject() &&
S.Context.hasSameUnqualifiedType(Entity.getType(), CurInitExpr->getType());
SourceLocation Loc;
switch (Entity.getKind()) {
case InitializedEntity::EK_Result:
if (Entity.getType()->isReferenceType())
return move(CurInit);
Loc = Entity.getReturnLoc();
break;
@ -3131,38 +3138,20 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S,
break;
case InitializedEntity::EK_Variable:
if (Entity.getType()->isReferenceType() ||
Kind.getKind() != InitializationKind::IK_Copy)
return move(CurInit);
Loc = Entity.getDecl()->getLocation();
break;
case InitializedEntity::EK_ArrayElement:
case InitializedEntity::EK_Member:
if (Entity.getType()->isReferenceType() ||
Kind.getKind() != InitializationKind::IK_Copy)
return move(CurInit);
Loc = CurInitExpr->getLocStart();
break;
case InitializedEntity::EK_Parameter:
// FIXME: Do we need this initialization for a parameter?
return move(CurInit);
case InitializedEntity::EK_New:
case InitializedEntity::EK_Temporary:
case InitializedEntity::EK_New:
case InitializedEntity::EK_Base:
case InitializedEntity::EK_VectorElement:
// We don't need to copy for any of these initialized entities.
return move(CurInit);
Loc = CurInitExpr->getLocStart();
break;
}
CXXRecordDecl *Class = 0;
if (const RecordType *Record = CurInitExpr->getType()->getAs<RecordType>())
Class = cast<CXXRecordDecl>(Record->getDecl());
if (!Class)
return move(CurInit);
// Perform overload resolution using the class's copy constructors.
DeclarationName ConstructorName
= S.Context.DeclarationNames.getCXXConstructorName(
@ -3171,7 +3160,7 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S,
OverloadCandidateSet CandidateSet(Loc);
for (llvm::tie(Con, ConEnd) = Class->lookup(ConstructorName);
Con != ConEnd; ++Con) {
// Find the constructor (which may be a template).
// Only consider copy constructors.
CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(*Con);
if (!Constructor || Constructor->isInvalidDecl() ||
!Constructor->isCopyConstructor())
@ -3181,7 +3170,7 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S,
= DeclAccessPair::make(Constructor, Constructor->getAccess());
S.AddOverloadCandidate(Constructor, FoundDecl,
&CurInitExpr, 1, CandidateSet);
}
}
OverloadCandidateSet::iterator Best;
switch (S.BestViableFunction(CandidateSet, Loc, Best)) {
@ -3218,9 +3207,9 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S,
Best->FoundDecl.getAccess());
CurInit.release();
return S.BuildCXXConstructExpr(Loc, CurInitExpr->getType(),
return S.BuildCXXConstructExpr(Loc, Entity.getType().getNonReferenceType(),
cast<CXXConstructorDecl>(Best->Function),
/*Elidable=*/true,
Elidable,
Sema::MultiExprArg(S,
(void**)&CurInitExpr, 1));
}
@ -3474,7 +3463,9 @@ InitializationSequence::Perform(Sema &S,
CastKind = CastExpr::CK_UserDefinedConversion;
}
if (shouldBindAsTemporary(Entity, IsCopy))
bool RequiresCopy = !IsCopy &&
getKind() != InitializationSequence::ReferenceBinding;
if (RequiresCopy || shouldBindAsTemporary(Entity))
CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
CurInitExpr = CurInit.takeAs<Expr>();
@ -3483,8 +3474,8 @@ InitializationSequence::Perform(Sema &S,
CurInitExpr,
IsLvalue));
if (!IsCopy)
CurInit = CopyIfRequiredForEntity(S, Entity, Kind, move(CurInit));
if (RequiresCopy)
CurInit = CopyObject(S, Entity, Kind, move(CurInit));
break;
}
@ -3560,13 +3551,9 @@ InitializationSequence::Perform(Sema &S,
S.CheckConstructorAccess(Loc, Constructor,
Step->Function.FoundDecl.getAccess());
bool Elidable
= cast<CXXConstructExpr>((Expr *)CurInit.get())->isElidable();
if (shouldBindAsTemporary(Entity, Elidable))
if (shouldBindAsTemporary(Entity))
CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
if (!Elidable)
CurInit = CopyIfRequiredForEntity(S, Entity, Kind, move(CurInit));
break;
}

View File

@ -281,7 +281,7 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc,
DeclPtrTy ClassCatImpDecl,
IdentifierInfo *PropertyId,
IdentifierInfo *PropertyIvar) {
Decl *ClassImpDecl = ClassCatImpDecl.getAs<Decl>();
ObjCContainerDecl *ClassImpDecl = ClassCatImpDecl.getAs<ObjCContainerDecl>();
// Make sure we have a context for the property implementation declaration.
if (!ClassImpDecl) {
Diag(AtLoc, diag::error_missing_property_context);
@ -353,14 +353,11 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc,
ObjCInterfaceDecl *ClassDeclared;
Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared);
if (!Ivar) {
DeclContext *EnclosingContext = cast_or_null<DeclContext>(ClassImpDecl);
assert(EnclosingContext &&
"null DeclContext for synthesized ivar - ActOnPropertyImplDecl");
Ivar = ObjCIvarDecl::Create(Context, EnclosingContext, PropertyLoc,
Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, PropertyLoc,
PropertyIvar, PropType, /*Dinfo=*/0,
ObjCIvarDecl::Public,
(Expr *)0);
EnclosingContext->addDecl(Ivar);
ClassImpDecl->addDecl(Ivar);
IDecl->makeDeclVisibleInContext(Ivar, false);
property->setPropertyIvarDecl(Ivar);
@ -1072,15 +1069,10 @@ Sema::SynthesizeNewPropertyIvar(ObjCInterfaceDecl *IDecl,
ObjCIvarDecl *Ivar = 0;
ObjCPropertyDecl *Prop = LookupPropertyDecl(IDecl, NameII);
if (Prop && !Prop->isInvalidDecl()) {
DeclContext *EnclosingContext = cast_or_null<DeclContext>(IDecl);
QualType PropType = Context.getCanonicalType(Prop->getType());
assert(EnclosingContext &&
"null DeclContext for synthesized ivar - SynthesizeNewPropertyIvar");
Ivar = ObjCIvarDecl::Create(Context, EnclosingContext,
Prop->getLocation(),
NameII, PropType, /*Dinfo=*/0,
ObjCIvarDecl::Public,
(Expr *)0);
Ivar = ObjCIvarDecl::Create(Context, IDecl, Prop->getLocation(), NameII,
PropType, /*Dinfo=*/0,
ObjCIvarDecl::Public, (Expr *)0);
Ivar->setLexicalDeclContext(IDecl);
IDecl->addDecl(Ivar);
Prop->setPropertyIvarDecl(Ivar);

View File

@ -1,5 +1,5 @@
// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm-bc -o - | opt -std-compile-opts | llvm-dis | grep 'ret i32 6'
// RUN: %clang_cc1 -triple i386-unknown-unknown -x c++ %s -emit-llvm-bc -o - | opt -std-compile-opts | llvm-dis | grep 'ret i32 7'
// RUN: %clang_cc1 -triple i386-unknown-unknown %s -O3 -emit-llvm -o - | grep 'ret i32 6'
// RUN: %clang_cc1 -triple i386-unknown-unknown -x c++ %s -O3 -emit-llvm -o - | grep 'ret i32 7'
static enum { foo, bar = 1U } z;

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm-bc -o - %s | opt -std-compile-opts -S | grep "ret i32 2520"
// RUN: %clang_cc1 -triple i386-unknown-unknown -O3 -emit-llvm -o - %s | grep "ret i32 2520"
static int foo(unsigned i) {
void *addrs[] = { &&L1, &&L2, &&L3, &&L4, &&L5 };

View File

@ -1,18 +0,0 @@
// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t
// RUN: grep "ret i32" %t | count 1
// RUN: grep "ret i32 10" %t | count 1
// Ensure that default after a case range is not ignored.
static int f1(unsigned x) {
switch(x) {
case 10 ... 0xFFFFFFFF:
return 0;
default:
return 10;
}
}
int g() {
return f1(2);
}

View File

@ -1,20 +0,0 @@
// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t
// RUN: grep "ret i32 10" %t
// Ensure that this doesn't compile to infinite loop in g() due to
// miscompilation of fallthrough from default to a (tested) case
// range.
static int f0(unsigned x) {
switch(x) {
default:
x += 1;
case 10 ... 0xFFFFFFFF:
return 0;
}
}
int g() {
f0(1);
return 10;
}

View File

@ -1,23 +0,0 @@
// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t
// RUN: grep "ret i32" %t | count 2
// RUN: grep "ret i32 3" %t | count 2
// This generated incorrect code because of poor switch chaining.
int f1(int x) {
switch(x) {
default:
return 3;
case 10 ... 0xFFFFFFFF:
return 0;
}
}
// This just asserted because of the way case ranges were calculated.
int f2(int x) {
switch (x) {
default:
return 3;
case 10 ... -1:
return 0;
}
}

View File

@ -1,15 +0,0 @@
// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t
// RUN: grep "ret i32 %" %t
// Make sure return is not constant (if empty range is skipped or miscompiled)
int f0(unsigned x) {
switch(x) {
case 2:
// fallthrough empty range
case 10 ... 9:
return 10;
default:
return 0;
}
}

View File

@ -1,12 +0,0 @@
// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t
// RUN: grep "ret i32" %t | count 1
// RUN: grep "ret i32 3" %t | count 1
int f2(unsigned x) {
switch(x) {
default:
return 3;
case 0xFFFFFFFF ... 1: // This range should be empty because x is unsigned.
return 0;
}
}

View File

@ -100,3 +100,97 @@ void foo7(){
}
}
// CHECK: define i32 @f8(
// CHECK: ret i32 3
// CHECK: }
int f8(unsigned x) {
switch(x) {
default:
return 3;
case 0xFFFFFFFF ... 1: // This range should be empty because x is unsigned.
return 0;
}
}
// Ensure that default after a case range is not ignored.
//
// CHECK: define i32 @f9()
// CHECK: ret i32 10
// CHECK: }
static int f9_0(unsigned x) {
switch(x) {
case 10 ... 0xFFFFFFFF:
return 0;
default:
return 10;
}
}
int f9() {
return f9_0(2);
}
// Ensure that this doesn't compile to infinite loop in g() due to
// miscompilation of fallthrough from default to a (tested) case
// range.
//
// CHECK: define i32 @f10()
// CHECK: ret i32 10
// CHECK: }
static int f10_0(unsigned x) {
switch(x) {
default:
x += 1;
case 10 ... 0xFFFFFFFF:
return 0;
}
}
int f10() {
f10_0(1);
return 10;
}
// This generated incorrect code because of poor switch chaining.
//
// CHECK: define i32 @f11(
// CHECK: ret i32 3
// CHECK: }
int f11(int x) {
switch(x) {
default:
return 3;
case 10 ... 0xFFFFFFFF:
return 0;
}
}
// This just asserted because of the way case ranges were calculated.
//
// CHECK: define i32 @f12(
// CHECK: ret i32 3
// CHECK: }
int f12(int x) {
switch (x) {
default:
return 3;
case 10 ... -1:
return 0;
}
}
// Make sure return is not constant (if empty range is skipped or miscompiled)
//
// CHECK: define i32 @f13(
// CHECK: ret i32 %
// CHECK: }
int f13(unsigned x) {
switch(x) {
case 2:
// fallthrough empty range
case 10 ... 9:
return 10;
default:
return 0;
}
}

View File

@ -0,0 +1,29 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s
struct Foo {
Foo();
Foo(const Foo&);
};
struct Bar {
Bar();
operator const Foo&() const;
};
void f(Foo);
// CHECK: define void @_Z1g3Foo(%struct.Bar* %foo)
void g(Foo foo) {
// CHECK: call void @_ZN3BarC1Ev
// CHECK: @_ZNK3BarcvRK3FooEv
// CHECK: call void @_Z1f3Foo
f(Bar());
// CHECK: call void @_ZN3FooC1Ev
// CHECK: call void @_Z1f3Foo
f(Foo());
// CHECK: call void @_ZN3FooC1ERKS_
// CHECK: call void @_Z1f3Foo
f(foo);
// CHECK: ret
}

View File

@ -7,16 +7,21 @@ extern "C" int printf(...);
extern "C" void exit(int);
struct A {
A (const A&) { printf("A::A(const A&)\n"); }
A() {};
A (const A&) { printf("A::A(const A&)\n"); }
A() {};
~A() { printf("A::~A()\n"); }
};
struct B : public A {
B() {};
};
B(const B& Other) : A(Other) { printf("B::B(const B&)\n"); }
~B() { printf("B::~B()\n"); }
};
struct C : public B {
C() {};
C(const C& Other) : B(Other) { printf("C::C(const C&)\n"); }
~C() { printf("C::~C()\n"); }
};
struct X {
@ -24,6 +29,7 @@ struct X {
operator C&() {printf("X::operator C&()\n"); return c; }
X (const X&) { printf("X::X(const X&)\n"); }
X () { printf("X::X()\n"); }
~X () { printf("X::~X()\n"); }
B b;
C c;
};

View File

@ -104,7 +104,8 @@ struct test7_B1 : virtual test7_B2 { virtual void funcB1(); };
struct test7_D : test7_B2, virtual test7_B1 {
};
// CHECK-LP64: .zerofill __DATA,__common,_d7,16,3
// FIXME: we were checking for an alignment of 3 (?)
// CHECK-LP64: .zerofill __DATA,__common,_d7,16,
struct test3_B3 { virtual void funcB3(); };

View File

@ -128,10 +128,8 @@ void use_F(F<char> &fc) {
// CHECK: @_ZTI1FIlE = weak_odr constant
// F<int> is an explicit template instantiation declaration without a
// key function, so its vtable should have weak_odr linkage.
// CHECK: @_ZTV1FIiE = weak_odr constant
// CHECK: @_ZTS1FIiE = weak_odr constant
// CHECK: @_ZTI1FIiE = weak_odr constant
// key function, so its vtable should have external linkage.
// CHECK: @_ZTV1FIiE = external constant
// E<int> is an explicit template instantiation declaration. It has a
// key function that is not instantiated, so we should only reference

View File

@ -9,3 +9,13 @@ typedef float CGFloat;
// expected-error {{ expected ';' after method prototype}}
@end
// rdar: // 7822196
@interface A
(void) x; // expected-error {{method type specifier must start with '-' or '+'}} \
// expected-warning {{type specifier missing, defaults to 'int' [-Wimplicit-int]}} \
// expected-error {{cannot declare variable inside @interface or @protocol}}
(int)im; // expected-error {{method type specifier must start with '-' or '+'}} \
- ok;
@end

View File

@ -213,3 +213,30 @@ namespace PR6595 {
(void)(Cond? a : S);
}
}
namespace PR6757 {
struct Foo1 {
Foo1();
Foo1(const Foo1&);
};
struct Foo2 { };
struct Foo3 {
Foo3();
Foo3(Foo3&);
};
struct Bar {
operator const Foo1&() const;
operator const Foo2&() const;
operator const Foo3&() const;
};
void f() {
(void)(true ? Bar() : Foo1()); // okay
(void)(true ? Bar() : Foo2()); // okay
// FIXME: Diagnostic below could be improved
(void)(true ? Bar() : Foo3()); // expected-error{{incompatible operand types ('PR6757::Bar' and 'PR6757::Foo3')}}
}
}

View File

@ -21,3 +21,23 @@ struct foo {
// PR3600
void test(const foo *P) { P->bar(); } // expected-error{{cannot initialize object parameter of type 'foo' with an expression of type 'foo const'}}
namespace PR6757 {
struct Foo {
Foo();
Foo(Foo&);
};
struct Bar {
operator const Foo&() const;
};
void f(Foo); // expected-note{{candidate function not viable: no known conversion from 'PR6757::Bar' to 'PR6757::Foo' for 1st argument}}
// FIXME: This isn't really the right reason for the failure. We
// should fail after overload resolution.
void g(Foo foo) {
f(Bar()); // expected-error{{no matching function for call to 'f'}}
f(foo);
}
}

View File

@ -0,0 +1,11 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// rdar://7822210
@interface A @end
@implementation A @end // expected-note {{class implementation is declared here}}
@interface A () // expected-error {{cannot declare class extension for 'A' after class implementation}}
-(void) im0;
@end

View File

@ -23,12 +23,12 @@
//@synthesize howMany, what;
- (int) howMany {
return howMany;
return self.howMany;
}
// - (void) setHowMany: (int) value
- (NSString*) what {
return what;
return self.what;
}
// - (void) setWhat: (NSString*) value
@end
@ -44,12 +44,12 @@
// - (int) howMany
- (void) setHowMany: (int) value {
howMany = value;
self.howMany = value;
}
// - (NSString*) what
- (void) setWhat: (NSString*) value {
if (what != value) {
if (self.what != value) {
}
}
@end
@ -64,17 +64,17 @@
//@synthesize howMany, what; // REM: Redundant anyway
- (int) howMany {
return howMany;
return self.howMany;
}
- (void) setHowMany: (int) value {
howMany = value;
self.howMany = value;
}
- (NSString*) what {
return what;
return self.what;
}
- (void) setWhat: (NSString*) value {
if (what != value) {
if (self.what != value) {
}
}
@end