[PATCH] D13285: Fix for bug 24196: clang fails on assertion on complex doubles multiplication when EH is enabled

2015-09-30 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla created this revision.
d.zobnin.bugzilla added reviewers: rsmith, rjmccall.
d.zobnin.bugzilla added a subscriber: cfe-commits.

This patch fixes an assertion failure, caused by EmitCall function producing 
llvm::InvokeInst* when llvm::CallInst* is needed (when multiplication of 
complex arguments is being emitted).

http://reviews.llvm.org/D13285

Files:
  lib/CodeGen/CGCall.cpp
  lib/CodeGen/CGExprComplex.cpp
  lib/CodeGen/CodeGenFunction.h
  test/CodeGenCXX/complex_mul_call.cpp

Index: lib/CodeGen/CGExprComplex.cpp
===
--- lib/CodeGen/CGExprComplex.cpp
+++ lib/CodeGen/CGExprComplex.cpp
@@ -592,7 +592,7 @@
   llvm::Instruction *Call;
 
   RValue Res = CGF.EmitCall(FuncInfo, Func, ReturnValueSlot(), Args,
-nullptr, &Call);
+nullptr, &Call, /*forceCallInstCreation =*/ true);
   cast(Call)->setCallingConv(CGF.CGM.getBuiltinCC());
   cast(Call)->setDoesNotThrow();
 
Index: lib/CodeGen/CGCall.cpp
===
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -3102,9 +3102,17 @@
  ReturnValueSlot ReturnValue,
  const CallArgList &CallArgs,
  const Decl *TargetDecl,
- llvm::Instruction **callOrInvoke) {
+ llvm::Instruction **callOrInvoke,
+ bool forceCallInstCreation) {
   // FIXME: We no longer need the types from CallArgs; lift up and simplify.
 
+  // It may be nessesary to create a CallInst* even if TargetDecl is not given
+  // (e. g. when emitting a complex operation call). Without TargetDecl there 
is
+  // no way to check the NoUnwind attribute required for CallInst creation. Use
+  // specific flag then, but take care of possible logical violations.
+  assert(!(TargetDecl && forceCallInstCreation) &&
+ "Should not force creation of CallInst if TargetDecl is present!");
+
   // Handle struct-return functions by passing a pointer to the
   // location that we would like to return into.
   QualType RetTy = CallInfo.getReturnType();
@@ -3442,7 +3450,7 @@
 InvokeDest = getInvokeDest();
 
   llvm::CallSite CS;
-  if (!InvokeDest) {
+  if (!InvokeDest || forceCallInstCreation) {
 CS = Builder.CreateCall(Callee, IRCallArgs);
   } else {
 llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
Index: lib/CodeGen/CodeGenFunction.h
===
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -2651,7 +2651,8 @@
   ReturnValueSlot ReturnValue,
   const CallArgList &Args,
   const Decl *TargetDecl = nullptr,
-  llvm::Instruction **callOrInvoke = nullptr);
+  llvm::Instruction **callOrInvoke = nullptr,
+  bool forceCallInstCreation = false);
 
   RValue EmitCall(QualType FnType, llvm::Value *Callee, const CallExpr *E,
   ReturnValueSlot ReturnValue,
Index: test/CodeGenCXX/complex_mul_call.cpp
===
--- test/CodeGenCXX/complex_mul_call.cpp
+++ test/CodeGenCXX/complex_mul_call.cpp
@@ -0,0 +1,24 @@
+// Check that multiplication of complex arguments is performed properly without
+// assersion fails when exceptions are enabled.
+//
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexceptions 
-fcxx-exceptions -emit-llvm %s -o - | FileCheck %s
+
+struct A {
+  int x;
+  A() { x = 10; }
+  ~A() { x = 20; }
+};
+
+int main() {
+  {
+A a;
+double __complex__ d;
+float __complex__ f;
+// CHECK-LABEL: main
+// CHECK-DAG: call {{.*}} @__muldc3
+double __complex__ d1 = d * d;
+// CHECK-DAG: call {{.*}} @__mulsc3
+float __complex__ f1 = f * f;
+  }
+  return 0;
+}


Index: lib/CodeGen/CGExprComplex.cpp
===
--- lib/CodeGen/CGExprComplex.cpp
+++ lib/CodeGen/CGExprComplex.cpp
@@ -592,7 +592,7 @@
   llvm::Instruction *Call;
 
   RValue Res = CGF.EmitCall(FuncInfo, Func, ReturnValueSlot(), Args,
-nullptr, &Call);
+nullptr, &Call, /*forceCallInstCreation =*/ true);
   cast(Call)->setCallingConv(CGF.CGM.getBuiltinCC());
   cast(Call)->setDoesNotThrow();
 
Index: lib/CodeGen/CGCall.cpp
===
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -3102,9 +3102,17 @@
  ReturnValueSlot ReturnValue,
  const CallArgList &CallArgs,
  const Decl *TargetDecl,
- llvm::Instruction **callOrInvoke) {
+ llvm::Instruction **call

[PATCH] D14467: [MS] Fix for bug 25013 - #pragma vtordisp is unknown inside functions.

2015-11-06 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla created this revision.
d.zobnin.bugzilla added a reviewer: rnk.
d.zobnin.bugzilla added a subscriber: cfe-commits.

This patch adds support of #pragma vtordisp inside functions in attempt to 
improve compatibility. Microsoft compiler appears to save the stack of vtordisp 
modes on entry of struct methods' bodies and restore it on exit (method-local 
vtordisp).

http://reviews.llvm.org/D14467

Files:
  include/clang/Sema/Sema.h
  lib/Parse/ParseDeclCXX.cpp
  lib/Parse/ParseStmt.cpp
  test/Layout/ms-vtordisp-local.cpp
  test/SemaCXX/pragma-vtordisp.cpp

Index: lib/Parse/ParseDeclCXX.cpp
===
--- lib/Parse/ParseDeclCXX.cpp
+++ lib/Parse/ParseDeclCXX.cpp
@@ -2854,6 +2854,11 @@
 return DeclGroupPtrTy();
   }
 
+  if (Tok.is(tok::annot_pragma_ms_vtordisp)) {
+HandlePragmaMSVtorDisp();
+return DeclGroupPtrTy();
+  }
+
   // If we see a namespace here, a close brace was missing somewhere.
   if (Tok.is(tok::kw_namespace)) {
 DiagnoseUnexpectedNamespace(cast(TagDecl));
Index: lib/Parse/ParseStmt.cpp
===
--- lib/Parse/ParseStmt.cpp
+++ lib/Parse/ParseStmt.cpp
@@ -358,6 +358,11 @@
 HandlePragmaMSPragma();
 return StmtEmpty();
 
+  case tok::annot_pragma_ms_vtordisp:
+ProhibitAttributes(Attrs);
+HandlePragmaMSVtorDisp();
+return StmtEmpty();
+
   case tok::annot_pragma_loop_hint:
 ProhibitAttributes(Attrs);
 return ParsePragmaLoopHint(Stmts, OnlyStatement, TrailingElseLoc, Attrs);
@@ -885,6 +890,9 @@
 case tok::annot_pragma_ms_pragma:
   HandlePragmaMSPragma();
   break;
+case tok::annot_pragma_ms_vtordisp:
+  HandlePragmaMSVtorDisp();
+  break;
 default:
   checkForPragmas = false;
   break;
@@ -1895,6 +1903,11 @@
   PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc,
   "parsing function body");
 
+  // Save and reset current vtordisp stack if we have entered a C++ method body.
+  bool IsCXXMethod =
+  getLangOpts().CPlusPlus && Decl && isa(Decl);
+  Sema::VtorDispStackRAII SavedVtorDispStack(Actions, IsCXXMethod);
+
   // Do not enter a scope for the brace, as the arguments are in the same scope
   // (the function body) as the body itself.  Instead, just read the statement
   // list and put it into a CompoundStmt for safe keeping.
@@ -1934,6 +1947,11 @@
 return Actions.ActOnSkippedFunctionBody(Decl);
   }
 
+  // Save and reset current vtordisp stack if we have entered a C++ method body.
+  bool IsCXXMethod =
+  getLangOpts().CPlusPlus && Decl && isa(Decl);
+  Sema::VtorDispStackRAII SavedVtorDispStack(Actions, IsCXXMethod);
+
   SourceLocation LBraceLoc = Tok.getLocation();
   StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc, /*FnTry*/true));
   // If we failed to parse the try-catch, we just give the function an empty
Index: include/clang/Sema/Sema.h
===
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -1008,6 +1008,24 @@
 bool OldFPContractState : 1;
   };
 
+  /// Records and restores the vtordisp state on entry/exit of C++ method body.
+  class VtorDispStackRAII {
+  public:
+VtorDispStackRAII(Sema &S, bool ShouldSaveAndRestore)
+  : S(S), ShouldSaveAndRestore(ShouldSaveAndRestore), OldVtorDispStack() {
+  if (ShouldSaveAndRestore)
+OldVtorDispStack = S.VtorDispModeStack;
+}
+~VtorDispStackRAII() {
+  if (ShouldSaveAndRestore)
+S.VtorDispModeStack = OldVtorDispStack;
+}
+  private:
+Sema &S;
+bool ShouldSaveAndRestore;
+SmallVector OldVtorDispStack;
+  };
+
   void addImplicitTypedef(StringRef Name, QualType T);
 
 public:
Index: test/Layout/ms-vtordisp-local.cpp
===
--- test/Layout/ms-vtordisp-local.cpp
+++ test/Layout/ms-vtordisp-local.cpp
@@ -0,0 +1,194 @@
+// RUN: %clang_cc1 -fms-extensions -fexceptions -fcxx-exceptions -emit-llvm-only -triple x86_64-pc-win32 -fdump-record-layouts -fsyntax-only %s 2>&1 | FileCheck %s
+
+struct Base {
+  virtual ~Base() {}
+  virtual void BaseFunc() {}
+};
+
+#pragma vtordisp(0)
+
+struct Container {
+  static void f() try {
+#pragma vtordisp(2)
+struct HasVtorDisp : virtual Base {
+  virtual ~HasVtorDisp() {}
+  virtual void Func() {}
+};
+
+int x[sizeof(HasVtorDisp)];
+
+// HasVtorDisp: vtordisp because of pragma right before it.
+//
+// CHECK: *** Dumping AST Record Layout
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT:  0 | struct HasVtorDisp
+// CHECK-NEXT:  0 |   (HasVtorDisp vftable pointer)
+// CHECK-NEXT:  8 |   (HasVtorDisp vbtable pointer)
+// CHECK-NEXT: 20 |   (vtordisp for vbase Base)
+// CHECK-NEXT: 24 |   struct Base (virtual base)
+// CHECK-NEXT: 24 | (Base 

Re: [PATCH] D16219: PR8901: attribute "mode" rejected for enums and dependent types

2016-02-01 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla updated this revision to Diff 46521.
d.zobnin.bugzilla added a comment.

Thanks for the review!

Only updated the text of diagnostics, NFC.


http://reviews.llvm.org/D16219

Files:
  include/clang/Basic/Attr.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/AttributeList.h
  include/clang/Sema/Sema.h
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaTemplateInstantiateDecl.cpp
  test/CodeGen/attr-mode-enums.c
  test/CodeGenCXX/attr-mode-vector-types-tmpl.cpp
  test/Sema/attr-mode-enums.c
  test/Sema/attr-mode.c
  test/SemaCXX/attr-mode-tmpl.cpp

Index: lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -227,6 +227,14 @@
 Attr.getSpellingListIndex());
 }
 
+static void
+instantiateDependentModeAttr(Sema &S,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ const ModeAttr &Attr, Decl *New) {
+  S.AddModeAttr(Attr.getRange(), New, Attr.getMode(),
+Attr.getSpellingListIndex(), /*InInstantiation=*/true);
+}
+
 void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
 const Decl *Tmpl, Decl *New,
 LateInstantiatedAttrVec *LateAttrs,
@@ -265,6 +273,11 @@
   continue;
 }
 
+if (const ModeAttr *Mode = dyn_cast(TmplAttr)) {
+  instantiateDependentModeAttr(*this, TemplateArgs, *Mode, New);
+  continue;
+}
+
 // Existing DLL attribute on the instantiation takes precedence.
 if (TmplAttr->getKind() == attr::DLLExport ||
 TmplAttr->getKind() == attr::DLLImport) {
Index: lib/Sema/SemaDeclAttr.cpp
===
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -3297,6 +3297,8 @@
 /// attribute.
 static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth,
  bool &IntegerMode, bool &ComplexMode) {
+  IntegerMode = true;
+  ComplexMode = false;
   switch (Str.size()) {
   case 2:
 switch (Str[0]) {
@@ -3363,9 +3365,15 @@
   }
 
   IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident;
-  StringRef Str = Name->getName();
 
+  S.AddModeAttr(Attr.getRange(), D, Name, Attr.getAttributeSpellingListIndex());
+}
+
+void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
+   unsigned SpellingListIndex, bool InInstantiation) {
+  StringRef Str = Name->getName();
   normalizeName(Str);
+  SourceLocation AttrLoc = AttrRange.getBegin();
 
   unsigned DestWidth = 0;
   bool IntegerMode = true;
@@ -3381,99 +3389,126 @@
 if (VectorStringLength &&
 !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) &&
 VectorSize.isPowerOf2()) {
-  parseModeAttrArg(S, Str.substr(VectorStringLength + 1), DestWidth,
+  parseModeAttrArg(*this, Str.substr(VectorStringLength + 1), DestWidth,
IntegerMode, ComplexMode);
-  S.Diag(Attr.getLoc(), diag::warn_vector_mode_deprecated);
+  // Avoid duplicate warning from template instantiation.
+  if (!InInstantiation)
+Diag(AttrLoc, diag::warn_vector_mode_deprecated);
 } else {
   VectorSize = 0;
 }
   }
 
   if (!VectorSize)
-parseModeAttrArg(S, Str, DestWidth, IntegerMode, ComplexMode);
+parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode);
+
+  // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
+  // and friends, at least with glibc.
+  // FIXME: Make sure floating-point mappings are accurate
+  // FIXME: Support XF and TF types
+  if (!DestWidth) {
+Diag(AttrLoc, diag::err_machine_mode) << 0 /*Unknown*/ << Name;
+return;
+  }
 
   QualType OldTy;
   if (TypedefNameDecl *TD = dyn_cast(D))
 OldTy = TD->getUnderlyingType();
-  else
+  else if (EnumDecl *ED = dyn_cast(D)) {
+// Something like 'typedef enum { X } __attribute__((mode(XX))) T;'.
+// Try to get type from enum declaration, default to int.
+OldTy = ED->getIntegerType();
+if (OldTy.isNull())
+  OldTy = Context.IntTy;
+  } else
 OldTy = cast(D)->getType();
 
+  if (OldTy->isDependentType()) {
+D->addAttr(::new (Context)
+   ModeAttr(AttrRange, Context, Name, SpellingListIndex));
+return;
+  }
+
   // Base type can also be a vector type (see PR17453).
   // Distinguish between base type and base element type.
   QualType OldElemTy = OldTy;
   if (const VectorType *VT = OldTy->getAs())
 OldElemTy = VT->getElementType();
 
-  if (!OldElemTy->getAs() && !OldElemTy->isComplexType())
-S.Diag(Attr.getLoc(), diag::err_mode_not_primitive);
+  // GCC allows 'mode' attribute on enumeration types (even incomplete), except
+  // for vector modes. So, 'enum X __attribute__((mode(QI)));' forms a complete
+  // type, 'enum { A } 

[PATCH] D16770: [MS] PR26234: Allow typedef redefinition of equally qualified, sized and aligned types in C

2016-02-01 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla created this revision.
d.zobnin.bugzilla added reviewers: rnk, majnemer.
d.zobnin.bugzilla added a subscriber: cfe-commits.

Allow typedef redefinition with different types in C if the types are equally 
qualified, sized and aligned. MSVC allows such redefinition, emits warning 
C4142: "benign redefinition of type" and propagates the type from the first 
typedef declaration in the entire redeclaration chain. 

http://reviews.llvm.org/D16770

Files:
  include/clang/AST/ASTContext.h
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/AST/ASTContext.cpp
  lib/Sema/SemaDecl.cpp
  test/Sema/ms-benign-typedef-redef.c

Index: lib/AST/ASTContext.cpp
===
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -6723,6 +6723,43 @@
   return false;
 }
 
+bool ASTContext::areMSCompatibleTypesInC(QualType OldType, QualType NewType) {
+  assert(getLangOpts().MicrosoftExt &&
+ "This routine must be called in Microsoft mode only!");
+  assert(!getLangOpts().CPlusPlus && !getLangOpts().ObjC1 &&
+ !getLangOpts().ObjC2 && "This routine must be called in C mode only!");
+
+  QualType OldCan = getCanonicalType(OldType);
+  QualType NewCan = getCanonicalType(NewType);
+
+  if (OldCan.getCVRQualifiers() != NewCan.getCVRQualifiers())
+return false;
+
+  if (OldCan->isPointerType() && NewCan->isPointerType()) {
+QualType OldPointee = OldType->getPointeeType();
+QualType NewPointee = NewType->getPointeeType();
+// void * and char * are interchangeable.
+if ((OldPointee->isCharType() && NewPointee->isVoidType()) ||
+(OldPointee->isVoidType() && NewPointee->isCharType()))
+  return true;
+return areMSCompatibleTypesInC(OldPointee, NewPointee);
+  }
+
+  // Enum vs float not allowed.
+  if ((OldCan->isRealFloatingType() && NewCan->isEnumeralType()) ||
+  (OldCan->isEnumeralType() && NewCan->isRealFloatingType()))
+return false;
+
+  if (OldCan->isRealType() && NewCan->isRealType()) {
+auto OldTypeInfo = getTypeInfo(OldCan);
+auto NewTypeInfo = getTypeInfo(NewCan);
+return (OldTypeInfo.Width == NewTypeInfo.Width &&
+OldTypeInfo.Align == NewTypeInfo.Align);
+  }
+
+  return false;
+}
+
 //===--===//
 // ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's.
 //===--===//
Index: lib/Sema/SemaDecl.cpp
===
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -1842,9 +1842,31 @@
   Filter.done();
 }
 
+static bool areMSCompatibleTypedefs(TypedefNameDecl *OldTypedef,
+TypedefNameDecl *NewTypedef,
+ASTContext &Context) {
+#ifndef NDEBUG
+  const LangOptions &Opts = Context.getLangOpts();
+  assert(Opts.MicrosoftExt &&
+ "This routine must be called in Microsoft mode only!");
+  assert(!Opts.CPlusPlus && !Opts.ObjC1 && !Opts.ObjC2 &&
+ "This routine must be called in C mode only!");
+  assert(OldTypedef && NewTypedef && "Expected valid typedef declarations!");
+#endif
+
+  // If both are locally-scoped, emit an error.
+  if (!OldTypedef->getDeclContext()->isFileContext() &&
+  !NewTypedef->getDeclContext()->isFileContext())
+return false;
+
+  return Context.areMSCompatibleTypesInC(OldTypedef->getUnderlyingType(),
+ NewTypedef->getUnderlyingType());
+}
+
 bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) {
   QualType OldType;
-  if (TypedefNameDecl *OldTypedef = dyn_cast(Old))
+  TypedefNameDecl *OldTypedef = dyn_cast(Old);
+  if (OldTypedef)
 OldType = OldTypedef->getUnderlyingType();
   else
 OldType = Context.getTypeDeclType(Old);
@@ -1860,18 +1882,35 @@
 New->setInvalidDecl();
 return true;
   }
-  
+
   if (OldType != NewType &&
   !OldType->isDependentType() &&
   !NewType->isDependentType() &&
-  !Context.hasSameType(OldType, NewType)) { 
-int Kind = isa(Old) ? 1 : 0;
-Diag(New->getLocation(), diag::err_redefinition_different_typedef)
-  << Kind << NewType << OldType;
-if (Old->getLocation().isValid())
-  Diag(Old->getLocation(), diag::note_previous_definition);
-New->setInvalidDecl();
-return true;
+  !Context.hasSameType(OldType, NewType)) {
+const LangOptions &Opts = Context.getLangOpts();
+bool AllowedAsMicrosoftExtInC =
+Opts.MicrosoftExt && !Opts.CPlusPlus && !Opts.ObjC1 && !Opts.ObjC2 &&
+OldTypedef && areMSCompatibleTypedefs(OldTypedef, New, Context);
+
+SourceLocation OldLocation = Old->getLocation();
+if (AllowedAsMicrosoftExtInC) {
+  Diag(New->getLocation(), diag::warn_benign_redefinition_different_typedef)
+  << NewType << OldType;
+  if (OldTypedef->isModed())
+New->se

Re: [PATCH] D16630: PR23057: Fix assertion `Val && "isa<> used on a null pointer"' on invalid for-range expression

2016-02-02 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla added inline comments.


Comment at: lib/Parse/ParseStmt.cpp:1719-1724
@@ -1718,6 +1718,8 @@
   if (ForRange) {
+ExprResult CorrectedRange =
+Actions.CorrectDelayedTyposInExpr(ForRangeInit.RangeExpr.get());
 ForRangeStmt = Actions.ActOnCXXForRangeStmt(
 getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(),
-ForRangeInit.ColonLoc, ForRangeInit.RangeExpr.get(),
+ForRangeInit.ColonLoc, CorrectedRange.get(),
 T.getCloseLocation(), Sema::BFRK_Build);
 

majnemer wrote:
> Does this change effect all of the test cases you've added? If not, I think 
> it would make sense to split this change out.
Yes, this change is needed in all added test cases.
Without this we will have an assertion failure in ~Sema():

```
assert(DelayedTypos.empty() && "Uncorrected typos!");
```


http://reviews.llvm.org/D16630



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r259492 - Test commit (NFC).

2016-02-02 Thread Denis Zobnin via cfe-commits
Author: dzobnin
Date: Tue Feb  2 06:39:08 2016
New Revision: 259492

URL: http://llvm.org/viewvc/llvm-project?rev=259492&view=rev
Log:
Test commit (NFC).

Modified:
cfe/trunk/test/CodeGenCXX/alignment.cpp

Modified: cfe/trunk/test/CodeGenCXX/alignment.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/alignment.cpp?rev=259492&r1=259491&r2=259492&view=diff
==
--- cfe/trunk/test/CodeGenCXX/alignment.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/alignment.cpp Tue Feb  2 06:39:08 2016
@@ -32,7 +32,7 @@ namespace test0 {
 // CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]]
 // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 4
 b.onebit = int_source();
-
+
 // CHECK: [[B_P:%.*]] = load [[B]]*, [[B]]**
 // CHECK: [[FIELD_P:%.*]] = bitcast [[B]]* [[B_P]] to i8*
 // CHECK: [[VALUE:%.*]] = load i8, i8* [[FIELD_P]], align 4
@@ -60,7 +60,7 @@ namespace test0 {
 // CHECK: [[T2:%.*]] = or i8 [[T1]], [[T0]]
 // CHECK: store i8 [[T2]], i8* [[FIELD_P]], align 2
 c.onebit = int_source();
-
+
 // CHECK: [[C_P:%.*]] = load [[C]]*, [[C]]**
 // CHECK: [[T0:%.*]] = bitcast [[C]]* [[C_P]] to i8*
 // CHECK: [[T1:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 8


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r259497 - Fix for PR8901: attribute "mode" rejected for enums and dependent types.

2016-02-02 Thread Denis Zobnin via cfe-commits
Author: dzobnin
Date: Tue Feb  2 07:50:39 2016
New Revision: 259497

URL: http://llvm.org/viewvc/llvm-project?rev=259497&view=rev
Log:
Fix for PR8901: attribute "mode" rejected for enums and dependent types.

Allow "mode" attribute for enum types, except for vector modes, for 
compatibility with GCC.
Support "mode" attribute with dependent types.

Differential Revision: http://reviews.llvm.org/D16219

Added:
cfe/trunk/test/CodeGen/attr-mode-enums.c
cfe/trunk/test/CodeGenCXX/attr-mode-vector-types-tmpl.cpp
cfe/trunk/test/Sema/attr-mode-enums.c
cfe/trunk/test/SemaCXX/attr-mode-tmpl.cpp
Modified:
cfe/trunk/include/clang/Basic/Attr.td
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/AttributeList.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/Sema/attr-mode.c

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=259497&r1=259496&r2=259497&view=diff
==
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Tue Feb  2 07:50:39 2016
@@ -879,8 +879,8 @@ def MipsInterrupt : InheritableAttr, Tar
 
 def Mode : Attr {
   let Spellings = [GCC<"mode">];
-  let Subjects = SubjectList<[Var, TypedefName, Field], ErrorDiag,
- "ExpectedVariableFieldOrTypedef">;
+  let Subjects = SubjectList<[Var, Enum, TypedefName, Field], ErrorDiag,
+ "ExpectedVariableEnumFieldOrTypedef">;
   let Args = [IdentifierArgument<"Mode">];
   let Documentation = [Undocumented];
 }

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=259497&r1=259496&r2=259497&view=diff
==
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Feb  2 07:50:39 
2016
@@ -2448,7 +2448,7 @@ def warn_attribute_wrong_decl_type : War
   "variables, functions and classes|Objective-C protocols|"
   "functions and global variables|structs, unions, and typedefs|structs and 
typedefs|"
   "interface or protocol declarations|kernel functions|non-K&R-style 
functions|"
-  "variables, fields and typedefs}1">,
+  "variables, enums, fields and typedefs}1">,
   InGroup;
 def err_attribute_wrong_decl_type : Error;
 def warn_type_attribute_wrong_type : Warning<
@@ -2858,6 +2858,8 @@ def warn_vector_mode_deprecated : Warnin
   InGroup;
 def err_complex_mode_vector_type : Error<
   "type of machine mode does not support base vector types">;
+def err_enum_mode_vector_type : Error<
+  "mode %0 is not supported for enumeration types">;
 def warn_attribute_nonnull_no_pointers : Warning<
   "'nonnull' attribute applied to function with no pointer arguments">,
   InGroup;

Modified: cfe/trunk/include/clang/Sema/AttributeList.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=259497&r1=259496&r2=259497&view=diff
==
--- cfe/trunk/include/clang/Sema/AttributeList.h (original)
+++ cfe/trunk/include/clang/Sema/AttributeList.h Tue Feb  2 07:50:39 2016
@@ -856,7 +856,7 @@ enum AttributeDeclKind {
   ExpectedObjectiveCInterfaceOrProtocol,
   ExpectedKernelFunction,
   ExpectedFunctionWithProtoType,
-  ExpectedVariableFieldOrTypedef
+  ExpectedVariableEnumFieldOrTypedef
 };
 
 }  // end namespace clang

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=259497&r1=259496&r2=259497&view=diff
==
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Feb  2 07:50:39 2016
@@ -7750,6 +7750,10 @@ public:
   void AddLaunchBoundsAttr(SourceRange AttrRange, Decl *D, Expr *MaxThreads,
Expr *MinBlocks, unsigned SpellingListIndex);
 
+  /// AddModeAttr - Adds a mode attribute to a particular declaration.
+  void AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
+   unsigned SpellingListIndex, bool InInstantiation = false);
+
   
//======//
   // C++ Coroutines TS
   //

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=259497&r1=259496&r2=259497&view=diff
==
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Tue Feb  2 07:50:

[PATCH] D16808: [MCU] PR26438: Fix assertion failure on function returning an empty struct or union

2016-02-02 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla created this revision.
d.zobnin.bugzilla added reviewers: mkuper, rnk, DavidKreitzer.
d.zobnin.bugzilla added a subscriber: cfe-commits.

Add missing check for zero-sized type for MCU ABI in order to return zero-sized 
types (empty structs and unions) via memory.

http://reviews.llvm.org/D16808

Files:
  lib/CodeGen/TargetInfo.cpp
  test/CodeGen/mcu-struct-return.c

Index: lib/CodeGen/TargetInfo.cpp
===
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -1010,8 +1010,9 @@
   uint64_t Size = Context.getTypeSize(Ty);
 
   // For i386, type must be register sized.
-  // For the MCU ABI, it only needs to be <= 8-byte
-  if ((IsMCUABI && Size > 64) || (!IsMCUABI && !isRegisterSize(Size)))
+  // For the MCU ABI, it only needs to be positive <= 8-byte.
+  if ((IsMCUABI && (Size == 0 || Size > 64)) ||
+  (!IsMCUABI && !isRegisterSize(Size)))
return false;
 
   if (Ty->isVectorType()) {
Index: test/CodeGen/mcu-struct-return.c
===
--- test/CodeGen/mcu-struct-return.c
+++ test/CodeGen/mcu-struct-return.c
@@ -0,0 +1,66 @@
+// RUN: %clang_cc1 -triple i386-pc-elfiamcu -emit-llvm %s -o - | FileCheck %s
+
+// Structure that is more than 8 byte.
+struct Big {
+  double a[10];
+};
+
+// Empty union with zero size must be returned via memory.
+union U1 {
+} u1;
+
+// Too large union (80 bytes) must be returned via memory.
+union U2 {
+  struct Big b;
+} u2;
+
+// Aggregate union, must be returned in register.
+union U3 {
+  int x;
+} u3;
+
+// Empty struct with zero size, must be returned via memory.
+struct S1 {
+} s1;
+
+// Aggregate struct, must be returend in register.
+struct S2 {
+  int x;
+} s2;
+
+// CHECK: [[UNION1_TYPE:%.+]] = type {}
+// CHECK: [[UNION2_TYPE:%.+]] = type { [[STRUCT_TYPE:%.+]] }
+// CHECK: [[STRUCT_TYPE]] = type { [10 x double] }
+// CHECK: [[UNION3_TYPE:%.+]] = type { i32 }
+// CHECK: [[STRUCT1_TYPE:%.+]] = type {}
+// CHECK: [[STRUCT2_TYPE:%.+]] = type { i32 }
+
+union U1 foo1() { return u1; }
+union U2 foo2() { return u2; }
+union U3 foo3() { return u3; }
+struct S1 bar1() { return s1; }
+struct S2 bar2() { return s2; }
+// CHECK: define void @foo1([[UNION1_TYPE]]* noalias sret %{{.+}})
+// CHECK: define void @foo2([[UNION2_TYPE]]* noalias sret %{{.+}})
+// CHECK: define i32 @foo3()
+// CHECK: define void @bar1([[STRUCT1_TYPE]]* noalias sret %{{.+}})
+// CHECK: define i32 @bar2()
+
+void run() {
+  union U1 x1 = foo1();
+  union U2 x2 = foo2();
+  union U3 x3 = foo3();
+  struct S1 y1 = bar1();
+  struct S2 y2 = bar2();
+
+  // CHECK: [[X1:%.+]] = alloca [[UNION1_TYPE]]
+  // CHECK: [[X2:%.+]] = alloca [[UNION2_TYPE]]
+  // CHECK: [[X3:%.+]] = alloca [[UNION3_TYPE]]
+  // CHECK: [[Y1:%.+]] = alloca [[STRUCT1_TYPE]]
+  // CHECK: [[Y2:%.+]] = alloca [[STRUCT2_TYPE]]
+  // CHECK: call void @foo1([[UNION1_TYPE]]* sret [[X1]])
+  // CHECK: call void @foo2([[UNION2_TYPE]]* sret [[X2]])
+  // CHECK: {{.+}} = call i32 @foo3()
+  // CHECK: call void @bar1([[STRUCT1_TYPE]]* sret [[Y1]])
+  // CHECK: {{.+}} = call i32 @bar2()
+}


Index: lib/CodeGen/TargetInfo.cpp
===
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -1010,8 +1010,9 @@
   uint64_t Size = Context.getTypeSize(Ty);
 
   // For i386, type must be register sized.
-  // For the MCU ABI, it only needs to be <= 8-byte
-  if ((IsMCUABI && Size > 64) || (!IsMCUABI && !isRegisterSize(Size)))
+  // For the MCU ABI, it only needs to be positive <= 8-byte.
+  if ((IsMCUABI && (Size == 0 || Size > 64)) ||
+  (!IsMCUABI && !isRegisterSize(Size)))
return false;
 
   if (Ty->isVectorType()) {
Index: test/CodeGen/mcu-struct-return.c
===
--- test/CodeGen/mcu-struct-return.c
+++ test/CodeGen/mcu-struct-return.c
@@ -0,0 +1,66 @@
+// RUN: %clang_cc1 -triple i386-pc-elfiamcu -emit-llvm %s -o - | FileCheck %s
+
+// Structure that is more than 8 byte.
+struct Big {
+  double a[10];
+};
+
+// Empty union with zero size must be returned via memory.
+union U1 {
+} u1;
+
+// Too large union (80 bytes) must be returned via memory.
+union U2 {
+  struct Big b;
+} u2;
+
+// Aggregate union, must be returned in register.
+union U3 {
+  int x;
+} u3;
+
+// Empty struct with zero size, must be returned via memory.
+struct S1 {
+} s1;
+
+// Aggregate struct, must be returend in register.
+struct S2 {
+  int x;
+} s2;
+
+// CHECK: [[UNION1_TYPE:%.+]] = type {}
+// CHECK: [[UNION2_TYPE:%.+]] = type { [[STRUCT_TYPE:%.+]] }
+// CHECK: [[STRUCT_TYPE]] = type { [10 x double] }
+// CHECK: [[UNION3_TYPE:%.+]] = type { i32 }
+// CHECK: [[STRUCT1_TYPE:%.+]] = type {}
+// CHECK: [[STRUCT2_TYPE:%.+]] = type { i32 }
+
+union U1 foo1() { return u1; }
+union U2 foo2() { return u2; }
+union U3 foo3() { return u3; }
+struct S1 bar1() { return s1; }
+struct S2 bar2() { return s2; 

r259532 - PR23057: Fix assertion `Val && "isa<> used on a null pointer"' on invalid for-range expression.

2016-02-02 Thread Denis Zobnin via cfe-commits
Author: dzobnin
Date: Tue Feb  2 11:33:09 2016
New Revision: 259532

URL: http://llvm.org/viewvc/llvm-project?rev=259532&view=rev
Log:
PR23057: Fix assertion `Val && "isa<> used on a null pointer"' on invalid 
for-range expression.

Fix the issue discovered by fuzzing (PR23057, comment 18) by handling nullptr 
in Sema::ActOnCXXForRangeDecl 
and correct delayed typos in for-range expression before calling 
Sema::ActOnCXXForRangeStmt. Also fixes PR26288.

Differential Revision: http://reviews.llvm.org/D16630


Added:
cfe/trunk/test/Parser/cxx-invalid-for-range.cpp
Modified:
cfe/trunk/lib/Parse/ParseStmt.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp

Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=259532&r1=259531&r2=259532&view=diff
==
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Tue Feb  2 11:33:09 2016
@@ -1716,9 +1716,11 @@ StmtResult Parser::ParseForStatement(Sou
   StmtResult ForEachStmt;
 
   if (ForRange) {
+ExprResult CorrectedRange =
+Actions.CorrectDelayedTyposInExpr(ForRangeInit.RangeExpr.get());
 ForRangeStmt = Actions.ActOnCXXForRangeStmt(
 getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(),
-ForRangeInit.ColonLoc, ForRangeInit.RangeExpr.get(),
+ForRangeInit.ColonLoc, CorrectedRange.get(),
 T.getCloseLocation(), Sema::BFRK_Build);
 
   // Similarly, we need to do the semantic analysis for a for-range

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=259532&r1=259531&r2=259532&view=diff
==
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Feb  2 11:33:09 2016
@@ -9928,6 +9928,10 @@ void Sema::ActOnUninitializedDecl(Decl *
 }
 
 void Sema::ActOnCXXForRangeDecl(Decl *D) {
+  // If there is no declaration, there was an error parsing it. Ignore it.
+  if (!D)
+return;
+
   VarDecl *VD = dyn_cast(D);
   if (!VD) {
 Diag(D->getLocation(), diag::err_for_range_decl_must_be_var);

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp?rev=259532&r1=259531&r2=259532&view=diff
==
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp Tue Feb  2 11:33:09 
2016
@@ -18,6 +18,9 @@ void f() {
   for (struct S { S(int) {} } s : arr) { // expected-error {{types may not be 
defined in a for range declaration}}
   }
 
+  for (struct S { S(int) {} } s : Undeclared); // expected-error{{types may 
not be defined in a for range declaration}}
+   // expected-error@-1{{use of 
undeclared identifier 'Undeclared'}}
+
   new struct T {}; // expected-error {{'T' cannot be defined in a type 
specifier}}
   new struct A {}; // expected-error {{'A' cannot be defined in a type 
specifier}}
 

Added: cfe/trunk/test/Parser/cxx-invalid-for-range.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-invalid-for-range.cpp?rev=259532&view=auto
==
--- cfe/trunk/test/Parser/cxx-invalid-for-range.cpp (added)
+++ cfe/trunk/test/Parser/cxx-invalid-for-range.cpp Tue Feb  2 11:33:09 2016
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+// From PR23057 comment #18 (https://llvm.org/bugs/show_bug.cgi?id=23057#c18).
+
+namespace N {
+  int X[10]; // expected-note{{declared here
+}
+
+void f1() {
+  for (auto operator new : X); // expected-error{{'operator new' cannot be the 
name of a variable or data member}}
+   // expected-error@-1{{use of undeclared 
identifier 'X'; did you mean 'N::X'?}}
+}
+
+void f2() {
+  for (a operator== :) // expected-error{{'operator==' cannot be the name of a 
variable or data member}}
+   // expected-error@-1{{expected expression}}
+   // expected-error@-2{{unknown type name 'a'}}
+} // expected-error{{expected statement}}


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D16770: [MS] PR26234: Allow typedef redefinition of equally qualified, sized and aligned types in C

2016-02-03 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla updated this revision to Diff 46781.
d.zobnin.bugzilla added a comment.

Thanks for the review!

Updated the patch according to the comments: allowed only integer, enum and 
pointer types which have the same qualifiers, signedness, width and alignment. 
Changed the diagnostic text.

Please take a look.


http://reviews.llvm.org/D16770

Files:
  include/clang/AST/ASTContext.h
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/AST/ASTContext.cpp
  lib/Sema/SemaDecl.cpp
  test/Sema/ms-benign-typedef-redef.c

Index: lib/AST/ASTContext.cpp
===
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -6729,6 +6729,42 @@
   return false;
 }
 
+bool ASTContext::areMSCompatibleTypedefTypesInC(QualType OldType,
+QualType NewType) {
+  assert(getLangOpts().MSVCCompat &&
+ "This routine must be called in Microsoft mode only!");
+  assert(!getLangOpts().CPlusPlus && !getLangOpts().ObjC1 &&
+ !getLangOpts().ObjC2 && "This routine must be called in C mode only!");
+
+  QualType OldCan = getCanonicalType(OldType);
+  QualType NewCan = getCanonicalType(NewType);
+
+  if (OldCan.getCVRQualifiers() != NewCan.getCVRQualifiers())
+return false;
+
+  if (OldCan->isPointerType() && NewCan->isPointerType()) {
+QualType OldPointee = OldType->getPointeeType();
+QualType NewPointee = NewType->getPointeeType();
+// void * and char * are interchangeable.
+if ((OldPointee->isCharType() && NewPointee->isVoidType()) ||
+(OldPointee->isVoidType() && NewPointee->isCharType()))
+  return true;
+return areMSCompatibleTypedefTypesInC(OldPointee, NewPointee);
+  }
+
+  bool EquallySignedInts = (OldCan->isSignedIntegerOrEnumerationType() &&
+NewCan->isSignedIntegerOrEnumerationType()) ||
+   (OldCan->isUnsignedIntegerOrEnumerationType() &&
+NewCan->isUnsignedIntegerOrEnumerationType());
+  if (!EquallySignedInts)
+return false;
+
+  auto OldTypeInfo = getTypeInfo(OldCan);
+  auto NewTypeInfo = getTypeInfo(NewCan);
+  return (OldTypeInfo.Width == NewTypeInfo.Width &&
+  OldTypeInfo.Align == NewTypeInfo.Align);
+}
+
 //===--===//
 // ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's.
 //===--===//
Index: lib/Sema/SemaDecl.cpp
===
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -1842,9 +1842,30 @@
   Filter.done();
 }
 
+static bool areMSCompatibleTypedefs(TypedefNameDecl *Old, TypedefNameDecl *New,
+ASTContext &Context) {
+#ifndef NDEBUG
+  const LangOptions &Opts = Context.getLangOpts();
+  assert(Opts.MSVCCompat &&
+ "This routine must be called in Microsoft mode only!");
+  assert(!Opts.CPlusPlus && !Opts.ObjC1 && !Opts.ObjC2 &&
+ "This routine must be called in C mode only!");
+  assert(Old && New && "Expected valid typedef declarations!");
+#endif
+
+  // If both are locally-scoped, emit an error.
+  if (!Old->getDeclContext()->isFileContext() &&
+  !New->getDeclContext()->isFileContext())
+return false;
+
+  return Context.areMSCompatibleTypedefTypesInC(Old->getUnderlyingType(),
+New->getUnderlyingType());
+}
+
 bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) {
   QualType OldType;
-  if (TypedefNameDecl *OldTypedef = dyn_cast(Old))
+  auto *OldTypedef = dyn_cast(Old);
+  if (OldTypedef)
 OldType = OldTypedef->getUnderlyingType();
   else
 OldType = Context.getTypeDeclType(Old);
@@ -1860,18 +1881,35 @@
 New->setInvalidDecl();
 return true;
   }
-  
+
   if (OldType != NewType &&
   !OldType->isDependentType() &&
   !NewType->isDependentType() &&
-  !Context.hasSameType(OldType, NewType)) { 
-int Kind = isa(Old) ? 1 : 0;
-Diag(New->getLocation(), diag::err_redefinition_different_typedef)
-  << Kind << NewType << OldType;
-if (Old->getLocation().isValid())
-  Diag(Old->getLocation(), diag::note_previous_definition);
-New->setInvalidDecl();
-return true;
+  !Context.hasSameType(OldType, NewType)) {
+const LangOptions &Opts = Context.getLangOpts();
+bool AllowedAsMicrosoftExtInC =
+Opts.MSVCCompat && !Opts.CPlusPlus && !Opts.ObjC1 && !Opts.ObjC2 &&
+OldTypedef && areMSCompatibleTypedefs(OldTypedef, New, Context);
+
+SourceLocation OldLocation = Old->getLocation();
+if (AllowedAsMicrosoftExtInC) {
+  Diag(New->getLocation(), diag::warn_int_typedef_redefinition_ignored)
+  << NewType << OldType;
+  if (OldTypedef->isModed())
+New->setModedTypeSourceInfo(OldTypedef->getTypeSourceInfo(),
+

Re: [PATCH] D16770: [MS] PR26234: Allow typedef redefinition of equally qualified, sized and aligned types in C

2016-02-03 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla marked 5 inline comments as done.


Comment at: include/clang/AST/ASTContext.h:1772-1783
@@ -1771,1 +1771,14 @@
 
+  /// Return true is the given typedef types are compatible in C from MSVC's
+  /// point of view.
+  //
+  // Conditions:
+  //   1. Both typedef types are either integer, enumeral or pointers;
+  //   2. Both typedef types have the same qualifiers and signedness;
+  //   3. Both typedef types have the same size and alignment;
+  //   4. If pointers:
+  // 4.1. Levels of pointers are equal;
+  // 4.2. Pointee types are MSVC-compatible OR
+  // 4.3. One type points to void and another points to char.
+  bool areMSCompatibleTypedefTypesInC(QualType OldType, QualType NewType);
+

By the way, MSVC allows to redefine not anly typedefs, but variables as well 
(under the same conditions as typedefs):

```
int x;
long x;
```
Typedef redefinition seems to be just an example of MSVC's permissive behavior. 
The same for return types, etc.

So, do you think we need to compatible with MSVC, for example, also considering 
only integer types?


Comment at: include/clang/Basic/DiagnosticSemaKinds.td:4267-4269
@@ -4266,1 +4266,5 @@
   InGroup>;
+def warn_int_typedef_redefinition_ignored : ExtWarn<
+  "ignoring conflicting integer typedef redefinition%diff{ ($ vs $)|}0,1 "
+  "as a Microsoft extension; types have the same width and signedness">,
+  InGroup;

Done. I also tried to move the phrase "types have the same ..." to a note, but 
I thought the only warning was better.


http://reviews.llvm.org/D16770



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D16770: [MS] PR26234: Allow typedef redefinition of equally qualified, sized and aligned types in C

2016-02-03 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla marked 2 inline comments as done.
d.zobnin.bugzilla added a comment.

@thakis, it is needed to be able to compile SPEC2000: 255.vortex.


http://reviews.llvm.org/D16770



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D16808: [MCU] PR26438: Fix assertion failure on function returning an empty struct or union

2016-02-04 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla added a comment.

Thank you for the review!

David, I started from the assertion failure and was going up the call stack 
trying to understand what should be changed to make the assertion go away. In 
shouldReturnTypeInRegister() function there is isRegisterSize(Size) check for 
i386, which returns false for 0-sized types, so I naively assumed that for MCU 
we missed the 0-case check. I must have read the ABI more carefully...

While searching for a correct solution for this, I saw that 'void' return type 
is handled in classifyReturnType() by returning ABIArgInfo::getIgnore(). 
According to the comments:

  /// Ignore - Ignore the argument (treat as void). Useful for void and
  /// empty structs.
  Ignore,

Does it mean that we can treat empty structs and unions in return type as void 
in this case?


http://reviews.llvm.org/D16808



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D16808: [MCU] PR26438: Fix assertion failure on function returning an empty struct or union

2016-02-09 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla updated this revision to Diff 47333.
d.zobnin.bugzilla added a comment.

Thank you for your reply!

Added a check for empty struct/union to treat them as void, updated the test 
accordingly.

Please take a look.


http://reviews.llvm.org/D16808

Files:
  lib/CodeGen/TargetInfo.cpp
  test/CodeGen/mcu-struct-return.c

Index: lib/CodeGen/TargetInfo.cpp
===
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -364,7 +364,7 @@
 static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays) {
   const RecordType *RT = T->getAs();
   if (!RT)
-return 0;
+return false;
   const RecordDecl *RD = RT->getDecl();
   if (RD->hasFlexibleArrayMember())
 return false;
@@ -1119,6 +1119,10 @@
 if (!IsRetSmallStructInRegABI && !RetTy->isAnyComplexType())
   return getIndirectReturnResult(RetTy, State);
 
+// Ignore empty structs/unions.
+if (isEmptyRecord(getContext(), RetTy, true))
+  return ABIArgInfo::getIgnore();
+
 // Small structures which are register sized are generally returned
 // in a register.
 if (shouldReturnTypeInRegister(RetTy, getContext())) {
Index: test/CodeGen/mcu-struct-return.c
===
--- test/CodeGen/mcu-struct-return.c
+++ test/CodeGen/mcu-struct-return.c
@@ -0,0 +1,70 @@
+// RUN: %clang_cc1 -triple i386-pc-elfiamcu -emit-llvm %s -o - | FileCheck %s
+
+// Structure that is more than 8 byte.
+struct Big {
+  double a[10];
+};
+
+// Empty union with zero size must be returned as void.
+union U1 {
+} u1;
+
+// Too large union (80 bytes) must be returned via memory.
+union U2 {
+  struct Big b;
+} u2;
+
+// Must be returned in register.
+union U3 {
+  int x;
+} u3;
+
+// Empty struct with zero size, must be returned as void.
+struct S1 {
+} s1;
+
+// Must be returend in register.
+struct S2 {
+  int x;
+} s2;
+
+// CHECK: [[UNION1_TYPE:%.+]] = type {}
+// CHECK: [[UNION2_TYPE:%.+]] = type { [[STRUCT_TYPE:%.+]] }
+// CHECK: [[STRUCT_TYPE]] = type { [10 x double] }
+// CHECK: [[UNION3_TYPE:%.+]] = type { i32 }
+// CHECK: [[STRUCT1_TYPE:%.+]] = type {}
+// CHECK: [[STRUCT2_TYPE:%.+]] = type { i32 }
+
+union U1 foo1() { return u1; }
+union U2 foo2() { return u2; }
+union U3 foo3() { return u3; }
+struct S1 bar1() { return s1; }
+struct S2 bar2() { return s2; }
+struct S1 bar3(union U1 u) { return s1; }
+// CHECK: define void @foo1()
+// CHECK: define void @foo2([[UNION2_TYPE]]* noalias sret %{{.+}})
+// CHECK: define i32 @foo3()
+// CHECK: define void @bar1()
+// CHECK: define i32 @bar2()
+// CHECK: define void @bar3()
+
+void run() {
+  union U1 x1 = foo1();
+  union U2 x2 = foo2();
+  union U3 x3 = foo3();
+  struct S1 y1 = bar1();
+  struct S2 y2 = bar2();
+  struct S1 y3 = bar3(x1);
+
+  // CHECK: [[X1:%.+]] = alloca [[UNION1_TYPE]]
+  // CHECK: [[X2:%.+]] = alloca [[UNION2_TYPE]]
+  // CHECK: [[X3:%.+]] = alloca [[UNION3_TYPE]]
+  // CHECK: [[Y1:%.+]] = alloca [[STRUCT1_TYPE]]
+  // CHECK: [[Y2:%.+]] = alloca [[STRUCT2_TYPE]]
+  // CHECK: call void @foo1()
+  // CHECK: call void @foo2([[UNION2_TYPE]]* sret [[X2]])
+  // CHECK: {{.+}} = call i32 @foo3()
+  // CHECK: call void @bar1()
+  // CHECK: {{.+}} = call i32 @bar2()
+  // CHECK: call void @bar3()
+}


Index: lib/CodeGen/TargetInfo.cpp
===
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -364,7 +364,7 @@
 static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays) {
   const RecordType *RT = T->getAs();
   if (!RT)
-return 0;
+return false;
   const RecordDecl *RD = RT->getDecl();
   if (RD->hasFlexibleArrayMember())
 return false;
@@ -1119,6 +1119,10 @@
 if (!IsRetSmallStructInRegABI && !RetTy->isAnyComplexType())
   return getIndirectReturnResult(RetTy, State);
 
+// Ignore empty structs/unions.
+if (isEmptyRecord(getContext(), RetTy, true))
+  return ABIArgInfo::getIgnore();
+
 // Small structures which are register sized are generally returned
 // in a register.
 if (shouldReturnTypeInRegister(RetTy, getContext())) {
Index: test/CodeGen/mcu-struct-return.c
===
--- test/CodeGen/mcu-struct-return.c
+++ test/CodeGen/mcu-struct-return.c
@@ -0,0 +1,70 @@
+// RUN: %clang_cc1 -triple i386-pc-elfiamcu -emit-llvm %s -o - | FileCheck %s
+
+// Structure that is more than 8 byte.
+struct Big {
+  double a[10];
+};
+
+// Empty union with zero size must be returned as void.
+union U1 {
+} u1;
+
+// Too large union (80 bytes) must be returned via memory.
+union U2 {
+  struct Big b;
+} u2;
+
+// Must be returned in register.
+union U3 {
+  int x;
+} u3;
+
+// Empty struct with zero size, must be returned as void.
+struct S1 {
+} s1;
+
+// Must be returend in register.
+struct S2 {
+  int x;
+} s2;
+
+// CHECK: [[UNION1_TYPE:%.+]] = type {}
+// CHECK: 

r260373 - Fix assertion "Chunk.Kind == DeclaratorChunk::Function" with attributed type.

2016-02-10 Thread Denis Zobnin via cfe-commits
Author: dzobnin
Date: Wed Feb 10 05:23:48 2016
New Revision: 260373

URL: http://llvm.org/viewvc/llvm-project?rev=260373&view=rev
Log:
Fix assertion "Chunk.Kind == DeclaratorChunk::Function" with attributed type.

This patch is to upgrade FunctionTypeUnwrapper for correct processing of
AttributedType. Fixes PR25786.
Patch by Alexander Makarov.

Differential Revision: http://reviews.llvm.org/D15373

Added:
cfe/trunk/test/CodeGen/pr25786.c
cfe/trunk/test/Sema/pr25786.c
Modified:
cfe/trunk/lib/Sema/SemaType.cpp

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=260373&r1=260372&r2=260373&view=diff
==
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Wed Feb 10 05:23:48 2016
@@ -5370,6 +5370,7 @@ namespace {
   struct FunctionTypeUnwrapper {
 enum WrapKind {
   Desugar,
+  Attributed,
   Parens,
   Pointer,
   BlockPointer,
@@ -5402,6 +5403,9 @@ namespace {
 } else if (isa(Ty)) {
   T = cast(Ty)->getPointeeType();
   Stack.push_back(Reference);
+} else if (isa(Ty)) {
+  T = cast(Ty)->getEquivalentType();
+  Stack.push_back(Attributed);
 } else {
   const Type *DTy = Ty->getUnqualifiedDesugaredType();
   if (Ty == DTy) {
@@ -5450,6 +5454,9 @@ namespace {
 // information.
 return wrap(C, Old->getUnqualifiedDesugaredType(), I);
 
+  case Attributed:
+return wrap(C, cast(Old)->getEquivalentType(), I);
+
   case Parens: {
 QualType New = wrap(C, cast(Old)->getInnerType(), I);
 return C.getParenType(New);

Added: cfe/trunk/test/CodeGen/pr25786.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/pr25786.c?rev=260373&view=auto
==
--- cfe/trunk/test/CodeGen/pr25786.c (added)
+++ cfe/trunk/test/CodeGen/pr25786.c Wed Feb 10 05:23:48 2016
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | 
FileCheck %s
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -emit-llvm -o - %s | 
FileCheck %s --check-prefix=CHECK-OK
+
+void (__attribute__((regparm(3), stdcall)) *pf) ();
+void (__attribute__((regparm(2), stdcall)) foo)(int a) {
+}
+// CHECK: @pf = common global void (...)* null
+// CHECK: define void @foo(i32 %a)
+
+// CHECK-OK: @pf = common global void (...)* null
+// CHECK-OK: define x86_stdcallcc void @foo(i32 inreg %a)

Added: cfe/trunk/test/Sema/pr25786.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/pr25786.c?rev=260373&view=auto
==
--- cfe/trunk/test/Sema/pr25786.c (added)
+++ cfe/trunk/test/Sema/pr25786.c Wed Feb 10 05:23:48 2016
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -DTEST -fsyntax-only 
-verify %s
+// RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fsyntax-only -verify %s
+
+#if TEST
+void (__attribute__((regparm(3), stdcall)) *pf) (); //expected-warning 
{{calling convention 'stdcall' ignored for this target}}
+void (__attribute__((regparm(2), stdcall)) foo)(int a) { //expected-warning 
{{calling convention 'stdcall' ignored for this target}}
+}
+#else
+//expected-no-diagnostics
+void (__attribute__((regparm(3), stdcall)) *pf) ();
+void (__attribute__((regparm(2), stdcall)) foo)(int a) {}
+#endif


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r260510 - [MCU] Fix assertion failure on function returning empty union.

2016-02-11 Thread Denis Zobnin via cfe-commits
Author: dzobnin
Date: Thu Feb 11 05:26:03 2016
New Revision: 260510

URL: http://llvm.org/viewvc/llvm-project?rev=260510&view=rev
Log:
[MCU] Fix assertion failure on function returning empty union.

Treat empty struct/union in return type as void for MCU ABI. PR26438.

Differential Revision: http://reviews.llvm.org/D16808

Added:
cfe/trunk/test/CodeGen/mcu-struct-return.c
Modified:
cfe/trunk/lib/CodeGen/TargetInfo.cpp

Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=260510&r1=260509&r2=260510&view=diff
==
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Thu Feb 11 05:26:03 2016
@@ -364,7 +364,7 @@ static bool isEmptyField(ASTContext &Con
 static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays) {
   const RecordType *RT = T->getAs();
   if (!RT)
-return 0;
+return false;
   const RecordDecl *RD = RT->getDecl();
   if (RD->hasFlexibleArrayMember())
 return false;
@@ -1119,6 +1119,10 @@ ABIArgInfo X86_32ABIInfo::classifyReturn
 if (!IsRetSmallStructInRegABI && !RetTy->isAnyComplexType())
   return getIndirectReturnResult(RetTy, State);
 
+// Ignore empty structs/unions.
+if (isEmptyRecord(getContext(), RetTy, true))
+  return ABIArgInfo::getIgnore();
+
 // Small structures which are register sized are generally returned
 // in a register.
 if (shouldReturnTypeInRegister(RetTy, getContext())) {

Added: cfe/trunk/test/CodeGen/mcu-struct-return.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/mcu-struct-return.c?rev=260510&view=auto
==
--- cfe/trunk/test/CodeGen/mcu-struct-return.c (added)
+++ cfe/trunk/test/CodeGen/mcu-struct-return.c Thu Feb 11 05:26:03 2016
@@ -0,0 +1,70 @@
+// RUN: %clang_cc1 -triple i386-pc-elfiamcu -emit-llvm %s -o - | FileCheck %s
+
+// Structure that is more than 8 byte.
+struct Big {
+  double a[10];
+};
+
+// Empty union with zero size must be returned as void.
+union U1 {
+} u1;
+
+// Too large union (80 bytes) must be returned via memory.
+union U2 {
+  struct Big b;
+} u2;
+
+// Must be returned in register.
+union U3 {
+  int x;
+} u3;
+
+// Empty struct with zero size, must be returned as void.
+struct S1 {
+} s1;
+
+// Must be returend in register.
+struct S2 {
+  int x;
+} s2;
+
+// CHECK: [[UNION1_TYPE:%.+]] = type {}
+// CHECK: [[UNION2_TYPE:%.+]] = type { [[STRUCT_TYPE:%.+]] }
+// CHECK: [[STRUCT_TYPE]] = type { [10 x double] }
+// CHECK: [[UNION3_TYPE:%.+]] = type { i32 }
+// CHECK: [[STRUCT1_TYPE:%.+]] = type {}
+// CHECK: [[STRUCT2_TYPE:%.+]] = type { i32 }
+
+union U1 foo1() { return u1; }
+union U2 foo2() { return u2; }
+union U3 foo3() { return u3; }
+struct S1 bar1() { return s1; }
+struct S2 bar2() { return s2; }
+struct S1 bar3(union U1 u) { return s1; }
+// CHECK: define void @foo1()
+// CHECK: define void @foo2([[UNION2_TYPE]]* noalias sret %{{.+}})
+// CHECK: define i32 @foo3()
+// CHECK: define void @bar1()
+// CHECK: define i32 @bar2()
+// CHECK: define void @bar3()
+
+void run() {
+  union U1 x1 = foo1();
+  union U2 x2 = foo2();
+  union U3 x3 = foo3();
+  struct S1 y1 = bar1();
+  struct S2 y2 = bar2();
+  struct S1 y3 = bar3(x1);
+
+  // CHECK: [[X1:%.+]] = alloca [[UNION1_TYPE]]
+  // CHECK: [[X2:%.+]] = alloca [[UNION2_TYPE]]
+  // CHECK: [[X3:%.+]] = alloca [[UNION3_TYPE]]
+  // CHECK: [[Y1:%.+]] = alloca [[STRUCT1_TYPE]]
+  // CHECK: [[Y2:%.+]] = alloca [[STRUCT2_TYPE]]
+  // CHECK: call void @foo1()
+  // CHECK: call void @foo2([[UNION2_TYPE]]* sret [[X2]])
+  // CHECK: {{.+}} = call i32 @foo3()
+  // CHECK: call void @bar1()
+  // CHECK: {{.+}} = call i32 @bar2()
+  // CHECK: call void @bar3()
+}


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18700: [Inline asm][GCC compatibility] Handle %v-prefixed code in inline assembly

2016-04-27 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla added a comment.

This is just a weekly friendly ping.
Please take a look at the new patch!

Thank you,
Denis Zobnin


http://reviews.llvm.org/D18700



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r267866 - [MS] Improved implementation of MS stack pragmas (vtordisp, *_seg)

2016-04-28 Thread Denis Zobnin via cfe-commits
Author: dzobnin
Date: Thu Apr 28 05:13:18 2016
New Revision: 267866

URL: http://llvm.org/viewvc/llvm-project?rev=267866&view=rev
Log:
[MS] Improved implementation of MS stack pragmas (vtordisp, *_seg)

Rework implementation of several MS pragmas that use internal stack:
vtordisp, {bss|code|const|data}_seg.
This patch:
  1. Makes #pragma vtordisp use PragmaStack class as *_seg pragmas do;
  2. Fixes "#pragma vtordisp()" behavior: it shouldn't affect stack;
  3. Saves/restores the stacks on enter/exit a C++ method body.


Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Parse/ParsePragma.cpp
cfe/trunk/lib/Parse/ParseStmt.cpp
cfe/trunk/lib/Sema/Sema.cpp
cfe/trunk/lib/Sema/SemaAttr.cpp
cfe/trunk/test/CodeGenCXX/sections.cpp
cfe/trunk/test/SemaCXX/pragma-vtordisp.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=267866&r1=267865&r2=267866&view=diff
==
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Apr 28 05:13:18 2016
@@ -327,40 +327,21 @@ public:
   LangOptions::PragmaMSPointersToMembersKind
   MSPointerToMemberRepresentationMethod;
 
-  enum PragmaVtorDispKind {
-PVDK_Push,  ///< #pragma vtordisp(push, mode)
-PVDK_Set,   ///< #pragma vtordisp(mode)
-PVDK_Pop,   ///< #pragma vtordisp(pop)
-PVDK_Reset  ///< #pragma vtordisp()
-  };
-
-  enum PragmaMsStackAction {
-PSK_Reset,// #pragma ()
-PSK_Set,  // #pragma ("name")
-PSK_Push, // #pragma (push[, id])
-PSK_Push_Set, // #pragma (push[, id], "name")
-PSK_Pop,  // #pragma (pop[, id])
-PSK_Pop_Set,  // #pragma (pop[, id], "name")
-  };
-
-  /// \brief Whether to insert vtordisps prior to virtual bases in the 
Microsoft
-  /// C++ ABI.  Possible values are 0, 1, and 2, which mean:
-  ///
-  /// 0: Suppress all vtordisps
-  /// 1: Insert vtordisps in the presence of vbase overrides and non-trivial
-  ///structors
-  /// 2: Always insert vtordisps to support RTTI on partially constructed
-  ///objects
-  ///
-  /// The stack always has at least one element in it.
-  SmallVector VtorDispModeStack;
-
   /// Stack of active SEH __finally scopes.  Can be empty.
   SmallVector CurrentSEHFinally;
 
   /// \brief Source location for newly created implicit MSInheritanceAttrs
   SourceLocation ImplicitMSInheritanceAttrLoc;
 
+  enum PragmaMsStackAction {
+PSK_Reset = 0x0,// #pragma ()
+PSK_Set   = 0x1,// #pragma (value)
+PSK_Push  = 0x2,// #pragma (push[, id])
+PSK_Pop   = 0x4,// #pragma (pop[, id])
+PSK_Push_Set  = PSK_Push | PSK_Set, // #pragma (push[, id], value)
+PSK_Pop_Set   = PSK_Pop | PSK_Set,  // #pragma (pop[, id], value)
+  };
+
   template
   struct PragmaStack {
 struct Slot {
@@ -377,18 +358,84 @@ public:
  PragmaMsStackAction Action,
  llvm::StringRef StackSlotLabel,
  ValueType Value);
-explicit PragmaStack(const ValueType &Value)
-  : CurrentValue(Value) {}
+
+// MSVC seems to add artificial slots to #pragma stacks on entering a C++
+// method body to restore the stacks on exit, so it works like this:
+//
+//   struct S {
+// #pragma (push, InternalPragmaSlot, )
+// void Method {}
+// #pragma (pop, InternalPragmaSlot)
+//   };
+//
+// It works even with #pragma vtordisp, although MSVC doesn't support
+//   #pragma vtordisp(push [, id], n)
+// syntax.
+//
+// Push / pop a named sentinel slot.
+void SentinelAction(PragmaMsStackAction Action, StringRef Label) {
+  assert((Action == PSK_Push || Action == PSK_Pop) &&
+ "Can only push / pop #pragma stack sentinels!");
+  Act(CurrentPragmaLocation, Action, Label, CurrentValue);
+}
+
+// Constructors.
+explicit PragmaStack(const ValueType &Default)
+: DefaultValue(Default), CurrentValue(Default) {}
+
 SmallVector Stack;
+ValueType DefaultValue; // Value used for PSK_Reset action.
 ValueType CurrentValue;
 SourceLocation CurrentPragmaLocation;
   };
   // FIXME: We should serialize / deserialize these if they occur in a PCH (but
   // we shouldn't do so if they're in a module).
+
+  /// \brief Whether to insert vtordisps prior to virtual bases in the 
Microsoft
+  /// C++ ABI.  Possible values are 0, 1, and 2, which mean:
+  ///
+  /// 0: Suppress all vtordisps
+  /// 1: Insert vtordisps in the presence of vbase overrides and non-trivial
+  ///structors
+  /// 2: Always insert vtordisps to support RTTI on partially constructed
+  ///objects
+  PragmaStack VtorDispStack;
   PragmaStack DataSegStack;
   PragmaStack BSSSegStack;
   PragmaStack ConstSegStack;
   PragmaStack CodeSegStack;
+  // TODO:

r267870 - Revert "[MS] Improved implementation of MS stack pragmas (vtordisp, *_seg)"

2016-04-28 Thread Denis Zobnin via cfe-commits
Author: dzobnin
Date: Thu Apr 28 06:32:10 2016
New Revision: 267870

URL: http://llvm.org/viewvc/llvm-project?rev=267870&view=rev
Log:
Revert "[MS] Improved implementation of MS stack pragmas (vtordisp, *_seg)"

This reverts commit r267866.

Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Parse/ParsePragma.cpp
cfe/trunk/lib/Parse/ParseStmt.cpp
cfe/trunk/lib/Sema/Sema.cpp
cfe/trunk/lib/Sema/SemaAttr.cpp
cfe/trunk/test/CodeGenCXX/sections.cpp
cfe/trunk/test/SemaCXX/pragma-vtordisp.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=267870&r1=267869&r2=267870&view=diff
==
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Apr 28 06:32:10 2016
@@ -327,21 +327,40 @@ public:
   LangOptions::PragmaMSPointersToMembersKind
   MSPointerToMemberRepresentationMethod;
 
+  enum PragmaVtorDispKind {
+PVDK_Push,  ///< #pragma vtordisp(push, mode)
+PVDK_Set,   ///< #pragma vtordisp(mode)
+PVDK_Pop,   ///< #pragma vtordisp(pop)
+PVDK_Reset  ///< #pragma vtordisp()
+  };
+
+  enum PragmaMsStackAction {
+PSK_Reset,// #pragma ()
+PSK_Set,  // #pragma ("name")
+PSK_Push, // #pragma (push[, id])
+PSK_Push_Set, // #pragma (push[, id], "name")
+PSK_Pop,  // #pragma (pop[, id])
+PSK_Pop_Set,  // #pragma (pop[, id], "name")
+  };
+
+  /// \brief Whether to insert vtordisps prior to virtual bases in the 
Microsoft
+  /// C++ ABI.  Possible values are 0, 1, and 2, which mean:
+  ///
+  /// 0: Suppress all vtordisps
+  /// 1: Insert vtordisps in the presence of vbase overrides and non-trivial
+  ///structors
+  /// 2: Always insert vtordisps to support RTTI on partially constructed
+  ///objects
+  ///
+  /// The stack always has at least one element in it.
+  SmallVector VtorDispModeStack;
+
   /// Stack of active SEH __finally scopes.  Can be empty.
   SmallVector CurrentSEHFinally;
 
   /// \brief Source location for newly created implicit MSInheritanceAttrs
   SourceLocation ImplicitMSInheritanceAttrLoc;
 
-  enum PragmaMsStackAction {
-PSK_Reset = 0x0,// #pragma ()
-PSK_Set   = 0x1,// #pragma (value)
-PSK_Push  = 0x2,// #pragma (push[, id])
-PSK_Pop   = 0x4,// #pragma (pop[, id])
-PSK_Push_Set  = PSK_Push | PSK_Set, // #pragma (push[, id], value)
-PSK_Pop_Set   = PSK_Pop | PSK_Set,  // #pragma (pop[, id], value)
-  };
-
   template
   struct PragmaStack {
 struct Slot {
@@ -358,84 +377,18 @@ public:
  PragmaMsStackAction Action,
  llvm::StringRef StackSlotLabel,
  ValueType Value);
-
-// MSVC seems to add artificial slots to #pragma stacks on entering a C++
-// method body to restore the stacks on exit, so it works like this:
-//
-//   struct S {
-// #pragma (push, InternalPragmaSlot, )
-// void Method {}
-// #pragma (pop, InternalPragmaSlot)
-//   };
-//
-// It works even with #pragma vtordisp, although MSVC doesn't support
-//   #pragma vtordisp(push [, id], n)
-// syntax.
-//
-// Push / pop a named sentinel slot.
-void SentinelAction(PragmaMsStackAction Action, StringRef Label) {
-  assert((Action == PSK_Push || Action == PSK_Pop) &&
- "Can only push / pop #pragma stack sentinels!");
-  Act(CurrentPragmaLocation, Action, Label, CurrentValue);
-}
-
-// Constructors.
-explicit PragmaStack(const ValueType &Default)
-: DefaultValue(Default), CurrentValue(Default) {}
-
+explicit PragmaStack(const ValueType &Value)
+  : CurrentValue(Value) {}
 SmallVector Stack;
-ValueType DefaultValue; // Value used for PSK_Reset action.
 ValueType CurrentValue;
 SourceLocation CurrentPragmaLocation;
   };
   // FIXME: We should serialize / deserialize these if they occur in a PCH (but
   // we shouldn't do so if they're in a module).
-
-  /// \brief Whether to insert vtordisps prior to virtual bases in the 
Microsoft
-  /// C++ ABI.  Possible values are 0, 1, and 2, which mean:
-  ///
-  /// 0: Suppress all vtordisps
-  /// 1: Insert vtordisps in the presence of vbase overrides and non-trivial
-  ///structors
-  /// 2: Always insert vtordisps to support RTTI on partially constructed
-  ///objects
-  PragmaStack VtorDispStack;
   PragmaStack DataSegStack;
   PragmaStack BSSSegStack;
   PragmaStack ConstSegStack;
   PragmaStack CodeSegStack;
-  // TODO: Change implementation of #pragma pack to use PragmaStack<> approach.
-
-  // RAII object to psuh / pop sentinel slots for all MS #pragma stacks.
-  // Actions should be performed only if we enter / exit a C++ method body.
-  class PragmaStackSentinelRAII {
-  public:
-PragmaStack

r268029 - Recommit "[MS] Improved implementation of stack pragmas (vtordisp, *_seg)"

2016-04-29 Thread Denis Zobnin via cfe-commits
Author: dzobnin
Date: Fri Apr 29 06:27:00 2016
New Revision: 268029

URL: http://llvm.org/viewvc/llvm-project?rev=268029&view=rev
Log:
Recommit "[MS] Improved implementation of stack pragmas (vtordisp, *_seg)"

Slightly updated version, double-checked build and tests.
Improve implementation of MS pragmas that use stack + compatibility fixes.
This patch:
  1. Changes implementation of #pragma vtordisp to use PragmaStack class
 that other stack pragmas use;
  2. Fixes "#pragma vtordisp()" behavior - it shouldn't affect the stack;
  3. Supports "save-restore" of pragma stacks on enter / exit a C++ method
 body, as MSVC does.

TODO:
  1. Change implementation of #pragma pack to use the same approach;
  2. Introduce diagnostics on popping named stack slots, as MSVC does.

Reviewers:
  rnk, thakis

Differential revision: http://reviews.llvm.org/D19361

Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Parse/ParsePragma.cpp
cfe/trunk/lib/Parse/ParseStmt.cpp
cfe/trunk/lib/Sema/Sema.cpp
cfe/trunk/lib/Sema/SemaAttr.cpp
cfe/trunk/test/CodeGenCXX/sections.cpp
cfe/trunk/test/SemaCXX/pragma-vtordisp.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=268029&r1=268028&r2=268029&view=diff
==
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Apr 29 06:27:00 2016
@@ -327,40 +327,21 @@ public:
   LangOptions::PragmaMSPointersToMembersKind
   MSPointerToMemberRepresentationMethod;
 
-  enum PragmaVtorDispKind {
-PVDK_Push,  ///< #pragma vtordisp(push, mode)
-PVDK_Set,   ///< #pragma vtordisp(mode)
-PVDK_Pop,   ///< #pragma vtordisp(pop)
-PVDK_Reset  ///< #pragma vtordisp()
-  };
-
-  enum PragmaMsStackAction {
-PSK_Reset,// #pragma ()
-PSK_Set,  // #pragma ("name")
-PSK_Push, // #pragma (push[, id])
-PSK_Push_Set, // #pragma (push[, id], "name")
-PSK_Pop,  // #pragma (pop[, id])
-PSK_Pop_Set,  // #pragma (pop[, id], "name")
-  };
-
-  /// \brief Whether to insert vtordisps prior to virtual bases in the 
Microsoft
-  /// C++ ABI.  Possible values are 0, 1, and 2, which mean:
-  ///
-  /// 0: Suppress all vtordisps
-  /// 1: Insert vtordisps in the presence of vbase overrides and non-trivial
-  ///structors
-  /// 2: Always insert vtordisps to support RTTI on partially constructed
-  ///objects
-  ///
-  /// The stack always has at least one element in it.
-  SmallVector VtorDispModeStack;
-
   /// Stack of active SEH __finally scopes.  Can be empty.
   SmallVector CurrentSEHFinally;
 
   /// \brief Source location for newly created implicit MSInheritanceAttrs
   SourceLocation ImplicitMSInheritanceAttrLoc;
 
+  enum PragmaMsStackAction {
+PSK_Reset = 0x0,// #pragma ()
+PSK_Set   = 0x1,// #pragma (value)
+PSK_Push  = 0x2,// #pragma (push[, id])
+PSK_Pop   = 0x4,// #pragma (pop[, id])
+PSK_Push_Set  = PSK_Push | PSK_Set, // #pragma (push[, id], value)
+PSK_Pop_Set   = PSK_Pop | PSK_Set,  // #pragma (pop[, id], value)
+  };
+
   template
   struct PragmaStack {
 struct Slot {
@@ -377,18 +358,66 @@ public:
  PragmaMsStackAction Action,
  llvm::StringRef StackSlotLabel,
  ValueType Value);
-explicit PragmaStack(const ValueType &Value)
-  : CurrentValue(Value) {}
+
+// MSVC seems to add artificial slots to #pragma stacks on entering a C++
+// method body to restore the stacks on exit, so it works like this:
+//
+//   struct S {
+// #pragma (push, InternalPragmaSlot, )
+// void Method {}
+// #pragma (pop, InternalPragmaSlot)
+//   };
+//
+// It works even with #pragma vtordisp, although MSVC doesn't support
+//   #pragma vtordisp(push [, id], n)
+// syntax.
+//
+// Push / pop a named sentinel slot.
+void SentinelAction(PragmaMsStackAction Action, StringRef Label) {
+  assert((Action == PSK_Push || Action == PSK_Pop) &&
+ "Can only push / pop #pragma stack sentinels!");
+  Act(CurrentPragmaLocation, Action, Label, CurrentValue);
+}
+
+// Constructors.
+explicit PragmaStack(const ValueType &Default)
+: DefaultValue(Default), CurrentValue(Default) {}
+
 SmallVector Stack;
+ValueType DefaultValue; // Value used for PSK_Reset action.
 ValueType CurrentValue;
 SourceLocation CurrentPragmaLocation;
   };
   // FIXME: We should serialize / deserialize these if they occur in a PCH (but
   // we shouldn't do so if they're in a module).
+
+  /// \brief Whether to insert vtordisps prior to virtual bases in the 
Microsoft
+  /// C++ ABI.  Possible values are 0, 1, and 2, which mean:
+  ///
+  /// 0: Suppress all vtordisps
+  /// 1

Re: [PATCH] D19361: [MS] Improved implementation of MS stack pragmas (vtordisp, *_seg)

2016-04-29 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla added a comment.

Reid, thanks for review! I've changed the patch according to your comments and 
also moved implementation of RAII object to SemaAttr.cpp file (implementation 
in header broke many buildbots).

Nico, I will look at serialization and try to implement the desired behavior, 
thank you!


Repository:
  rL LLVM

http://reviews.llvm.org/D19361



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18700: [Inline asm][GCC compatibility] Handle %v-prefixed code in inline assembly

2016-04-29 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla updated this revision to Diff 55581.
d.zobnin.bugzilla added a comment.
Herald added a subscriber: joker.eph.

Updated the patch after r266292 commit: [ASTImporter] Implement some 
expression-related AST node import.


http://reviews.llvm.org/D18700

Files:
  include/clang/AST/Stmt.h
  lib/AST/ASTImporter.cpp
  lib/AST/Stmt.cpp
  lib/Sema/SemaStmtAsm.cpp
  test/CodeGen/avx-v-modifier-inline-asm.cpp

Index: lib/AST/Stmt.cpp
===
--- lib/AST/Stmt.cpp
+++ lib/AST/Stmt.cpp
@@ -632,6 +632,14 @@
 
   CurPtr = NameEnd+1;
   continue;
+} else if (*Begin == 'v') {
+  // GCC accepts code staring with "%v", e. g. "%vpcmpestri" and transforms
+  // it into "vpcmpestri" instruction if target processor supports AVX and
+  // into "pcmpestri" otherwise.
+  if (SupportsAVX)
+CurStringPiece = "v" + CurStringPiece;
+  CurStringPiece += EscapedChar;
+  continue;
 }
 
 DiagOffs = CurPtr-StrStart-1;
@@ -682,13 +690,15 @@
 //===--===//
 
 GCCAsmStmt::GCCAsmStmt(const ASTContext &C, SourceLocation asmloc,
-   bool issimple, bool isvolatile, unsigned numoutputs,
-   unsigned numinputs, IdentifierInfo **names,
-   StringLiteral **constraints, Expr **exprs,
-   StringLiteral *asmstr, unsigned numclobbers,
-   StringLiteral **clobbers, SourceLocation rparenloc)
-  : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
-numinputs, numclobbers), RParenLoc(rparenloc), AsmStr(asmstr) {
+   bool issimple, bool isvolatile, bool supportsavx,
+   unsigned numoutputs, unsigned numinputs,
+   IdentifierInfo **names, StringLiteral **constraints,
+   Expr **exprs, StringLiteral *asmstr,
+   unsigned numclobbers, StringLiteral **clobbers,
+   SourceLocation rparenloc)
+: AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
+  numinputs, numclobbers),
+  RParenLoc(rparenloc), AsmStr(asmstr), SupportsAVX(supportsavx) {
 
   unsigned NumExprs = NumOutputs + NumInputs;
 
Index: lib/AST/ASTImporter.cpp
===
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -4833,6 +4833,7 @@
 Importer.Import(S->getAsmLoc()),
 S->isSimple(),
 S->isVolatile(),
+S->getSupportsAVX(),
 S->getNumOutputs(),
 S->getNumInputs(),
 Names.data(),
Index: lib/Sema/SemaStmtAsm.cpp
===
--- lib/Sema/SemaStmtAsm.cpp
+++ lib/Sema/SemaStmtAsm.cpp
@@ -138,6 +138,75 @@
   return false;
 }
 
+// Collect all target features specified for the current context by the "target"
+// attribute. Start from current DeclContext and iterate its parents until we
+// find a function context.
+static void CollectTargetFeatures(Sema &S,
+  std::vector &TargetFeatures,
+  StringRef &TargetCPU) {
+  DeclContext *DC = S.CurContext;
+
+  auto Collect = [&TargetFeatures, &TargetCPU](const FunctionDecl *FD) {
+if (!FD)
+  return;
+if (const auto *TA = FD->getAttr()) {
+  TargetAttr::ParsedTargetAttr ParsedAttr = TA->parse();
+  TargetFeatures.insert(TargetFeatures.begin(), ParsedAttr.first.begin(),
+ParsedAttr.first.end());
+  if (TargetCPU == "")
+TargetCPU = ParsedAttr.second;
+}
+  };
+
+  // Climb up the tree of nested DeclContext-s, collecting the target features.
+  while (true) {
+if (isa(DC) || isa(DC) || isa(DC)) {
+  DC = DC->getParent();
+} else if (const auto *MD = dyn_cast(DC)) {
+  // Check if it's a lambda and collect its target features.
+  if (MD->getOverloadedOperator() == OO_Call &&
+  cast(DC->getParent())->isLambda()) {
+Collect(MD);
+  }
+  DC = DC->getParent()->getParent();
+} else {
+  // It's the nearest function, collect its features and break.
+  Collect(dyn_cast(DC));
+  break;
+}
+  }
+}
+
+// Check whether a particular target feature is enabled in current context,
+// either by command-line options or by __attribute__((__target__("..."))),
+// applied to any surrounding lambda or function.
+static bool TargetFeatureEnabled(Sema &S, StringRef Feature) {
+  const TargetInfo &TI = S.Context.getTargetInfo();
+  llvm::StringMap FeatureMap;
+  StringRef TargetCPU;
+  std::vector TargetFeatures;
+
+  // Collect target features and CPU from surrounding declarations.
+  CollectTargetFeatures(S, TargetFeatures, TargetCPU);
+
+  // Don't forget to add command-line features and CPU (lowest priority).
+  TargetFeatures.insert(TargetFeatures.begin

[PATCH] D19727: [MS] Improved implementation #pragma pack (MS pragmas, part 2)

2016-04-29 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla created this revision.
d.zobnin.bugzilla added a reviewer: rnk.
d.zobnin.bugzilla added subscribers: thakis, cfe-commits.

An attempt to make implementation of #pragma pack consistent with other "stack" 
pragmas. Also modifies #pragma options align, since it shares the stack with 
#pragma pack.
It is the first item from todo list in http://reviews.llvm.org/D19361

The patch doesn't change compiler's behavior, so the tests are not modified.
I'm planning to rework the pragmas' diagnostics in next patch -- it should be a 
common feature of all "stack" pragmas.

http://reviews.llvm.org/D19727

Files:
  include/clang/Sema/Sema.h
  lib/Parse/ParsePragma.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaAttr.cpp

Index: lib/Parse/ParsePragma.cpp
===
--- lib/Parse/ParsePragma.cpp
+++ lib/Parse/ParsePragma.cpp
@@ -337,11 +337,9 @@
 
 namespace {
 struct PragmaPackInfo {
-  Sema::PragmaPackKind Kind;
-  IdentifierInfo *Name;
+  Sema::PragmaMsStackAction Action;
+  StringRef SlotLabel;
   Token Alignment;
-  SourceLocation LParenLoc;
-  SourceLocation RParenLoc;
 };
 } // end anonymous namespace
 
@@ -356,8 +354,8 @@
 if (Alignment.isInvalid())
   return;
   }
-  Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
-  Info->LParenLoc, Info->RParenLoc);
+  Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
+  Alignment.get());
 }
 
 void Parser::HandlePragmaMSStruct() {
@@ -962,11 +960,10 @@
 return;
   }
 
-  Sema::PragmaPackKind Kind = Sema::PPK_Default;
-  IdentifierInfo *Name = nullptr;
+  Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
+  StringRef SlotLabel;
   Token Alignment;
   Alignment.startToken();
-  SourceLocation LParenLoc = Tok.getLocation();
   PP.Lex(Tok);
   if (Tok.is(tok::numeric_constant)) {
 Alignment = Tok;
@@ -976,18 +973,18 @@
 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
 // the push/pop stack.
 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
-if (PP.getLangOpts().ApplePragmaPack)
-  Kind = Sema::PPK_Push;
+Action =
+PP.getLangOpts().ApplePragmaPack ? Sema::PSK_Push_Set : Sema::PSK_Set;
   } else if (Tok.is(tok::identifier)) {
 const IdentifierInfo *II = Tok.getIdentifierInfo();
 if (II->isStr("show")) {
-  Kind = Sema::PPK_Show;
+  Action = Sema::PSK_Show;
   PP.Lex(Tok);
 } else {
   if (II->isStr("push")) {
-Kind = Sema::PPK_Push;
+Action = Sema::PSK_Push;
   } else if (II->isStr("pop")) {
-Kind = Sema::PPK_Pop;
+Action = Sema::PSK_Pop;
   } else {
 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
 return;
@@ -998,11 +995,12 @@
 PP.Lex(Tok);
 
 if (Tok.is(tok::numeric_constant)) {
+  Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
   Alignment = Tok;
 
   PP.Lex(Tok);
 } else if (Tok.is(tok::identifier)) {
-  Name = Tok.getIdentifierInfo();
+  SlotLabel = Tok.getIdentifierInfo()->getName();
   PP.Lex(Tok);
 
   if (Tok.is(tok::comma)) {
@@ -1013,6 +1011,7 @@
   return;
 }
 
+Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
 Alignment = Tok;
 
 PP.Lex(Tok);
@@ -1027,7 +1026,7 @@
 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
 // the push/pop stack.
 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
-Kind = Sema::PPK_Pop;
+Action = Sema::PSK_Pop;
   }
 
   if (Tok.isNot(tok::r_paren)) {
@@ -1044,11 +1043,9 @@
 
   PragmaPackInfo *Info =
   PP.getPreprocessorAllocator().Allocate(1);
-  Info->Kind = Kind;
-  Info->Name = Name;
+  Info->Action = Action;
+  Info->SlotLabel = SlotLabel;
   Info->Alignment = Alignment;
-  Info->LParenLoc = LParenLoc;
-  Info->RParenLoc = RParenLoc;
 
   MutableArrayRef Toks(PP.getPreprocessorAllocator().Allocate(1),
   1);
Index: lib/Sema/Sema.cpp
===
--- lib/Sema/Sema.cpp
+++ lib/Sema/Sema.cpp
@@ -79,12 +79,13 @@
 Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
 CollectStats(false), CodeCompleter(CodeCompleter),
 CurContext(nullptr), OriginalLexicalContext(nullptr),
-PackContext(nullptr), MSStructPragmaOn(false),
+MSStructPragmaOn(false),
 MSPointerToMemberRepresentationMethod(
 LangOpts.getMSPointerToMemberRepresentationMethod()),
 VtorDispStack(MSVtorDispAttr::Mode(LangOpts.VtorDispMode)),
-DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr),
-CodeSegStack(nullptr), CurInitSeg(nullptr), VisContext(nullptr),
+PackStack(0), DataSegStack(nullptr), BSSSegStack(nullptr),
+ConstSegStack(nullptr), CodeSegStack(n

Re: [PATCH] D19727: [MS] Improved implementation #pragma pack (MS pragmas, part 2)

2016-04-29 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla added inline comments.


Comment at: lib/Sema/SemaAttr.cpp:277-278
@@ -276,4 @@
-  // empty.
-  Diag(PragmaLoc, diag::warn_pragma_pop_failed)
-  << "pack" << (Name ? "no record matching name" : "stack empty");
-

Here I removed the "no record matching name" diagnostics, which wasn't covered 
by any test.
I'm going to rework and restore it in future patch.


http://reviews.llvm.org/D19727



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r268085 - [MS] Make #pragma pack use PragmaStack<> class.

2016-04-29 Thread Denis Zobnin via cfe-commits
Author: dzobnin
Date: Fri Apr 29 13:17:40 2016
New Revision: 268085

URL: http://llvm.org/viewvc/llvm-project?rev=268085&view=rev
Log:
[MS] Make #pragma pack use PragmaStack<> class.

Make implementation of #pragma pack consistent with other "stack" pragmas.
Use PragmaStack<> class instead of old representation of internal stack.
Don't change compiler's behavior.

TODO:
  1. Introduce diagnostics on popping named slots from pragma stacks.

Reviewer: rnk

Differential revision: http://reviews.llvm.org/D19727

Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Parse/ParsePragma.cpp
cfe/trunk/lib/Sema/Sema.cpp
cfe/trunk/lib/Sema/SemaAttr.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=268085&r1=268084&r2=268085&view=diff
==
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Apr 29 13:17:40 2016
@@ -317,10 +317,6 @@ public:
   /// This is used as part of a hack to omit that class from ADL results.
   DeclarationName VAListTagName;
 
-  /// PackContext - Manages the stack for \#pragma pack. An alignment
-  /// of 0 indicates default alignment.
-  void *PackContext; // Really a "PragmaPackStack*"
-
   bool MSStructPragmaOn; // True when \#pragma ms_struct on
 
   /// \brief Controls member pointer representation format under the MS ABI.
@@ -338,6 +334,7 @@ public:
 PSK_Set   = 0x1,// #pragma (value)
 PSK_Push  = 0x2,// #pragma (push[, id])
 PSK_Pop   = 0x4,// #pragma (pop[, id])
+PSK_Show  = 0x8,// #pragma (show) -- only for "pack"!
 PSK_Push_Set  = PSK_Push | PSK_Set, // #pragma (push[, id], value)
 PSK_Pop_Set   = PSK_Pop | PSK_Set,  // #pragma (pop[, id], value)
   };
@@ -400,11 +397,15 @@ public:
   /// 2: Always insert vtordisps to support RTTI on partially constructed
   ///objects
   PragmaStack VtorDispStack;
+  // #pragma pack.
+  // Sentinel to represent when the stack is set to mac68k alignment.
+  static const unsigned kMac68kAlignmentSentinel = ~0U;
+  PragmaStack PackStack;
+  // Segment #pragmas.
   PragmaStack DataSegStack;
   PragmaStack BSSSegStack;
   PragmaStack ConstSegStack;
   PragmaStack CodeSegStack;
-  // TODO: Change implementation of #pragma pack to use PragmaStack<> approach.
 
   // RAII object to push / pop sentinel slots for all MS #pragma stacks.
   // Actions should be performed only if we enter / exit a C++ method body.
@@ -7658,20 +7659,9 @@ public:
   void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
SourceLocation PragmaLoc);
 
-  enum PragmaPackKind {
-PPK_Default, // #pragma pack([n])
-PPK_Show,// #pragma pack(show), only supported by MSVC.
-PPK_Push,// #pragma pack(push, [identifier], [n])
-PPK_Pop  // #pragma pack(pop, [identifier], [n])
-  };
-
   /// ActOnPragmaPack - Called on well formed \#pragma pack(...).
-  void ActOnPragmaPack(PragmaPackKind Kind,
-   IdentifierInfo *Name,
-   Expr *Alignment,
-   SourceLocation PragmaLoc,
-   SourceLocation LParenLoc,
-   SourceLocation RParenLoc);
+  void ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
+   StringRef SlotLabel, Expr *Alignment);
 
   /// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off].
   void ActOnPragmaMSStruct(PragmaMSStructKind Kind);

Modified: cfe/trunk/lib/Parse/ParsePragma.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParsePragma.cpp?rev=268085&r1=268084&r2=268085&view=diff
==
--- cfe/trunk/lib/Parse/ParsePragma.cpp (original)
+++ cfe/trunk/lib/Parse/ParsePragma.cpp Fri Apr 29 13:17:40 2016
@@ -337,11 +337,9 @@ void Parser::HandlePragmaVisibility() {
 
 namespace {
 struct PragmaPackInfo {
-  Sema::PragmaPackKind Kind;
-  IdentifierInfo *Name;
+  Sema::PragmaMsStackAction Action;
+  StringRef SlotLabel;
   Token Alignment;
-  SourceLocation LParenLoc;
-  SourceLocation RParenLoc;
 };
 } // end anonymous namespace
 
@@ -356,8 +354,8 @@ void Parser::HandlePragmaPack() {
 if (Alignment.isInvalid())
   return;
   }
-  Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
-  Info->LParenLoc, Info->RParenLoc);
+  Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
+  Alignment.get());
 }
 
 void Parser::HandlePragmaMSStruct() {
@@ -962,11 +960,10 @@ void PragmaPackHandler::HandlePragma(Pre
 return;
   }
 
-  Sema::PragmaPackKind Kind = Sema::PPK_Default;
-  IdentifierInfo *Name = nullptr;
+  Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
+  StringRef SlotL

r268129 - [NFC] Initialize a variable to make buildbot green.

2016-04-29 Thread Denis Zobnin via cfe-commits
Author: dzobnin
Date: Fri Apr 29 17:50:16 2016
New Revision: 268129

URL: http://llvm.org/viewvc/llvm-project?rev=268129&view=rev
Log:
[NFC] Initialize a variable to make buildbot green.

In r268085 "[MS] Make #pragma pack use PragmaStack<> class." there was an
uninitialized variable 'Alignment', which caused the following failure:
  http://lab.llvm.org:8011/builders/sanitizer-ppc64be-linux/builds/1758
Zero-initialize the variable to fix this failure.

Modified:
cfe/trunk/lib/Sema/SemaAttr.cpp

Modified: cfe/trunk/lib/Sema/SemaAttr.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaAttr.cpp?rev=268129&r1=268128&r2=268129&view=diff
==
--- cfe/trunk/lib/Sema/SemaAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaAttr.cpp Fri Apr 29 17:50:16 2016
@@ -78,7 +78,7 @@ void Sema::AddMsStructLayoutForRecord(Re
 void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
SourceLocation PragmaLoc) {
   PragmaMsStackAction Action = Sema::PSK_Reset;
-  unsigned Alignment;
+  unsigned Alignment = 0;
   switch (Kind) {
 // For all targets we support native and natural are the same.
 //


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D18652: [Inline asm] Correctly parse GCC-style asm line following MS-style asm line

2016-03-31 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla created this revision.
d.zobnin.bugzilla added a reviewer: echristo.
d.zobnin.bugzilla added a subscriber: cfe-commits.

Clang fails to compile the following code:

void f() {
  __asm mov ebx, ecx
  __asm__("movl %ecx, %edx");
}

reporting unexpected token "__asm__" at start of statement.
Quit parsing MS-style assembly if the following statement has GCC style to 
handle such code.

http://reviews.llvm.org/D18652

Files:
  lib/Parse/ParseStmtAsm.cpp
  test/CodeGen/inline-asm-mixed-style.c

Index: lib/Parse/ParseStmtAsm.cpp
===
--- lib/Parse/ParseStmtAsm.cpp
+++ lib/Parse/ParseStmtAsm.cpp
@@ -417,9 +417,10 @@
 // If this is a single-line __asm, we're done, except if the next
 // line begins with an __asm too, in which case we finish a comment
 // if needed and then keep processing the next line as a single
-// line __asm.
+// line __asm. Also break if the next __asm is followed by an '(' -
+// GCC-style asm.
 bool isAsm = Tok.is(tok::kw_asm);
-if (SingleLineMode && !isAsm)
+if (SingleLineMode && (!isAsm || NextToken().is(tok::l_paren)))
   break;
 // We're no longer in a comment.
 InAsmComment = false;
Index: test/CodeGen/inline-asm-mixed-style.c
===
--- test/CodeGen/inline-asm-mixed-style.c
+++ test/CodeGen/inline-asm-mixed-style.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple i386-unknown-unknown -fasm-blocks -fsyntax-only 
-verify %s
+// expected-no-diagnostics
+// RUN: %clang_cc1 -triple i386-unknown-unknown -fasm-blocks -emit-llvm -S %s 
-o - | FileCheck %s
+
+void f() {
+  __asm mov eax, ebx
+  __asm mov ebx, ecx
+  __asm__("movl %ecx, %edx");
+
+  // CHECK: movl%ebx, %eax
+  // CHECK: movl%ecx, %ebx
+  // CHECK: movl%ecx, %edx
+}


Index: lib/Parse/ParseStmtAsm.cpp
===
--- lib/Parse/ParseStmtAsm.cpp
+++ lib/Parse/ParseStmtAsm.cpp
@@ -417,9 +417,10 @@
 // If this is a single-line __asm, we're done, except if the next
 // line begins with an __asm too, in which case we finish a comment
 // if needed and then keep processing the next line as a single
-// line __asm.
+// line __asm. Also break if the next __asm is followed by an '(' -
+// GCC-style asm.
 bool isAsm = Tok.is(tok::kw_asm);
-if (SingleLineMode && !isAsm)
+if (SingleLineMode && (!isAsm || NextToken().is(tok::l_paren)))
   break;
 // We're no longer in a comment.
 InAsmComment = false;
Index: test/CodeGen/inline-asm-mixed-style.c
===
--- test/CodeGen/inline-asm-mixed-style.c
+++ test/CodeGen/inline-asm-mixed-style.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple i386-unknown-unknown -fasm-blocks -fsyntax-only -verify %s
+// expected-no-diagnostics
+// RUN: %clang_cc1 -triple i386-unknown-unknown -fasm-blocks -emit-llvm -S %s -o - | FileCheck %s
+
+void f() {
+  __asm mov eax, ebx
+  __asm mov ebx, ecx
+  __asm__("movl %ecx, %edx");
+
+  // CHECK: movl%ebx, %eax
+  // CHECK: movl%ecx, %ebx
+  // CHECK: movl%ecx, %edx
+}
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D18657: Propagate missing empty exception spec from function declared in system header

2016-03-31 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla created this revision.
d.zobnin.bugzilla added reviewers: doug.gregor, rjmccall.
d.zobnin.bugzilla added a subscriber: cfe-commits.

If new function is missing empty exception specification "throw()" and 
"throw()" came from system header, don't emit errors. It is already implemented 
in Clang, but taking into account only last redeclaration of a function. Look 
for declaration in system header up to the first declaration in redeclaration 
chain, as GCC seems to do.

This patch enables compilation of Facebook/ds2 application.

http://reviews.llvm.org/D18657

Files:
  lib/Sema/SemaExceptionSpec.cpp
  test/SemaCXX/Inputs/malloc.h
  test/SemaCXX/builtin-exception-spec.cpp

Index: lib/Sema/SemaExceptionSpec.cpp
===
--- lib/Sema/SemaExceptionSpec.cpp
+++ lib/Sema/SemaExceptionSpec.cpp
@@ -254,9 +254,15 @@
   // to many libc functions as an optimization. Unfortunately, that
   // optimization isn't permitted by the C++ standard, so we're forced
   // to work around it here.
-  if (MissingEmptyExceptionSpecification && NewProto &&
-  (Old->getLocation().isInvalid() ||
-   Context.getSourceManager().isInSystemHeader(Old->getLocation())) &&
+  bool IsFromSystemHeader = false;
+  for (const FunctionDecl *Prev = Old; Prev; Prev = Prev->getPreviousDecl())
+if (Prev->getLocation().isInvalid() ||
+Context.getSourceManager().isInSystemHeader(Prev->getLocation())) {
+  IsFromSystemHeader = true;
+  break;
+}
+
+  if (MissingEmptyExceptionSpecification && NewProto && IsFromSystemHeader &&
   Old->isExternC()) {
 New->setType(Context.getFunctionType(
 NewProto->getReturnType(), NewProto->getParamTypes(),
Index: test/SemaCXX/builtin-exception-spec.cpp
===
--- test/SemaCXX/builtin-exception-spec.cpp
+++ test/SemaCXX/builtin-exception-spec.cpp
@@ -4,4 +4,7 @@
 
 extern "C" {
 void *malloc(__SIZE_TYPE__);
+
+void MyFunc() __attribute__((__weak__));
+void MyFunc() { return; }
 }
Index: test/SemaCXX/Inputs/malloc.h
===
--- test/SemaCXX/Inputs/malloc.h
+++ test/SemaCXX/Inputs/malloc.h
@@ -1,3 +1,5 @@
 extern "C" {
 extern void *malloc (__SIZE_TYPE__ __size) throw () __attribute__ 
((__malloc__)) ;
+
+void MyFunc() throw();
 }


Index: lib/Sema/SemaExceptionSpec.cpp
===
--- lib/Sema/SemaExceptionSpec.cpp
+++ lib/Sema/SemaExceptionSpec.cpp
@@ -254,9 +254,15 @@
   // to many libc functions as an optimization. Unfortunately, that
   // optimization isn't permitted by the C++ standard, so we're forced
   // to work around it here.
-  if (MissingEmptyExceptionSpecification && NewProto &&
-  (Old->getLocation().isInvalid() ||
-   Context.getSourceManager().isInSystemHeader(Old->getLocation())) &&
+  bool IsFromSystemHeader = false;
+  for (const FunctionDecl *Prev = Old; Prev; Prev = Prev->getPreviousDecl())
+if (Prev->getLocation().isInvalid() ||
+Context.getSourceManager().isInSystemHeader(Prev->getLocation())) {
+  IsFromSystemHeader = true;
+  break;
+}
+
+  if (MissingEmptyExceptionSpecification && NewProto && IsFromSystemHeader &&
   Old->isExternC()) {
 New->setType(Context.getFunctionType(
 NewProto->getReturnType(), NewProto->getParamTypes(),
Index: test/SemaCXX/builtin-exception-spec.cpp
===
--- test/SemaCXX/builtin-exception-spec.cpp
+++ test/SemaCXX/builtin-exception-spec.cpp
@@ -4,4 +4,7 @@
 
 extern "C" {
 void *malloc(__SIZE_TYPE__);
+
+void MyFunc() __attribute__((__weak__));
+void MyFunc() { return; }
 }
Index: test/SemaCXX/Inputs/malloc.h
===
--- test/SemaCXX/Inputs/malloc.h
+++ test/SemaCXX/Inputs/malloc.h
@@ -1,3 +1,5 @@
 extern "C" {
 extern void *malloc (__SIZE_TYPE__ __size) throw () __attribute__ ((__malloc__)) ;
+
+void MyFunc() throw();
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D18698: [C11] PR24451: Allow restrict _Atomic pointers

2016-04-01 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla created this revision.
d.zobnin.bugzilla added a reviewer: rsmith.
d.zobnin.bugzilla added a subscriber: cfe-commits.

Treat _Atomic pointers as pointer types (check value type of AtomicType) in 
case of handling the "restrict" qualifier. Accept such code (so does GCC):

int * restrict _Atomic p;

http://reviews.llvm.org/D18698

Files:
  lib/Sema/SemaType.cpp
  test/Misc/ast-dump-restrict-atomic.c

Index: lib/Sema/SemaType.cpp
===
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -1663,12 +1663,18 @@
   if (T.isNull())
 return QualType();
 
+  QualType OriginalType = T;
+
   // Enforce C99 6.7.3p2: "Types other than pointer types derived from
   // object or incomplete types shall not be restrict-qualified."
   if (Qs.hasRestrict()) {
 unsigned DiagID = 0;
 QualType ProblemTy;
 
+// Handle code like "int * _Atomic restrict p".
+if (const AtomicType *AtomicT = T->getAs())
+  T = AtomicT->getValueType();
+
 if (T->isAnyPointerType() || T->isReferenceType() ||
 T->isMemberPointerType()) {
   QualType EltTy;
@@ -1696,7 +1702,7 @@
 }
   }
 
-  return Context.getQualifiedType(T, Qs);
+  return Context.getQualifiedType(OriginalType, Qs);
 }
 
 QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
Index: test/Misc/ast-dump-restrict-atomic.c
===
--- test/Misc/ast-dump-restrict-atomic.c
+++ test/Misc/ast-dump-restrict-atomic.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -std=c11 -ast-dump %s | FileCheck %s
+// RUN: %clang_cc1 -std=c11 -verify %s
+// expected-no-diagnostics
+
+int * _Atomic restrict a;
+int * restrict _Atomic b;
+int _Atomic * restrict c;
+volatile _Atomic int * restrict _Atomic const * restrict d;
+
+// CHECK: a '__restrict _Atomic(int *)'
+// CHECK: b '__restrict _Atomic(int *)'
+// CHECK: c '_Atomic(int) *__restrict'
+// CHECK: d 'const __restrict _Atomic(volatile _Atomic(int) *) *__restrict'


Index: lib/Sema/SemaType.cpp
===
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -1663,12 +1663,18 @@
   if (T.isNull())
 return QualType();
 
+  QualType OriginalType = T;
+
   // Enforce C99 6.7.3p2: "Types other than pointer types derived from
   // object or incomplete types shall not be restrict-qualified."
   if (Qs.hasRestrict()) {
 unsigned DiagID = 0;
 QualType ProblemTy;
 
+// Handle code like "int * _Atomic restrict p".
+if (const AtomicType *AtomicT = T->getAs())
+  T = AtomicT->getValueType();
+
 if (T->isAnyPointerType() || T->isReferenceType() ||
 T->isMemberPointerType()) {
   QualType EltTy;
@@ -1696,7 +1702,7 @@
 }
   }
 
-  return Context.getQualifiedType(T, Qs);
+  return Context.getQualifiedType(OriginalType, Qs);
 }
 
 QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
Index: test/Misc/ast-dump-restrict-atomic.c
===
--- test/Misc/ast-dump-restrict-atomic.c
+++ test/Misc/ast-dump-restrict-atomic.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -std=c11 -ast-dump %s | FileCheck %s
+// RUN: %clang_cc1 -std=c11 -verify %s
+// expected-no-diagnostics
+
+int * _Atomic restrict a;
+int * restrict _Atomic b;
+int _Atomic * restrict c;
+volatile _Atomic int * restrict _Atomic const * restrict d;
+
+// CHECK: a '__restrict _Atomic(int *)'
+// CHECK: b '__restrict _Atomic(int *)'
+// CHECK: c '_Atomic(int) *__restrict'
+// CHECK: d 'const __restrict _Atomic(volatile _Atomic(int) *) *__restrict'
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D18700: [Inline asm][GCC compatibility] Handle %v-prefixed code in inline assembly

2016-04-01 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla created this revision.
d.zobnin.bugzilla added a reviewer: echristo.
d.zobnin.bugzilla added a subscriber: cfe-commits.

Handle an inline assembly feature of GCC: code prefixed with "%v", e. g. 
"%vpcmpestri" is transformed into "vpcmpestri" instruction if target supports 
AVX and into "pcmpestri" otherwise.

Given the code:
```
void f(void* arg)
{
  __asm__ ("%vpcmpestri $0, (%1), %2"
   : "=c"(arg)
   : "r"(arg), "x"(arg));
}
```

"gcc -c test.c -o test.o" produces

```
movq   -0x10(%rbp),%xmm0
pcmpestri $0x0,(%rax),%xmm0
```

While "gcc -c -march=corei7-avx test.c -o test.o" produces

```
vmovq  %rdx,%xmm0
vpcmpestri $0x0,(%rax),%xmm0
```

http://reviews.llvm.org/D18700

Files:
  lib/AST/Stmt.cpp
  test/CodeGen/avx-inline-asm.c

Index: lib/AST/Stmt.cpp
===
--- lib/AST/Stmt.cpp
+++ lib/AST/Stmt.cpp
@@ -632,6 +632,14 @@
 
   CurPtr = NameEnd+1;
   continue;
+} else if (*Begin == 'v') {
+  // GCC accepts code staring with "%v", e. g. "%vpcmpestri" and transforms
+  // it into "vpcmpestri" instruction if target processor supports AVX and
+  // into "pcmpestri" otherwise.
+  if (C.getTargetInfo().hasFeature("avx"))
+CurStringPiece = "v" + CurStringPiece;
+  CurStringPiece += EscapedChar;
+  continue;
 }
 
 DiagOffs = CurPtr-StrStart-1;
Index: test/CodeGen/avx-inline-asm.c
===
--- test/CodeGen/avx-inline-asm.c
+++ test/CodeGen/avx-inline-asm.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -target-feature +avx 
-emit-llvm -S %s -o - | FileCheck %s -check-prefix=CHECK-AVX
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -emit-llvm -S %s -o - | 
FileCheck %s
+
+void f(void* arg)
+{
+  __asm__ ("%vpcmpestri $0, (%1), %2"
+   : "=c"(arg)
+   : "r"(arg), "x"(arg));
+
+  // CHECK: pcmpestri
+  // CHECK-AVX: vpcmpestri
+}


Index: lib/AST/Stmt.cpp
===
--- lib/AST/Stmt.cpp
+++ lib/AST/Stmt.cpp
@@ -632,6 +632,14 @@
 
   CurPtr = NameEnd+1;
   continue;
+} else if (*Begin == 'v') {
+  // GCC accepts code staring with "%v", e. g. "%vpcmpestri" and transforms
+  // it into "vpcmpestri" instruction if target processor supports AVX and
+  // into "pcmpestri" otherwise.
+  if (C.getTargetInfo().hasFeature("avx"))
+CurStringPiece = "v" + CurStringPiece;
+  CurStringPiece += EscapedChar;
+  continue;
 }
 
 DiagOffs = CurPtr-StrStart-1;
Index: test/CodeGen/avx-inline-asm.c
===
--- test/CodeGen/avx-inline-asm.c
+++ test/CodeGen/avx-inline-asm.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -target-feature +avx -emit-llvm -S %s -o - | FileCheck %s -check-prefix=CHECK-AVX
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -emit-llvm -S %s -o - | FileCheck %s
+
+void f(void* arg)
+{
+  __asm__ ("%vpcmpestri $0, (%1), %2"
+   : "=c"(arg)
+   : "r"(arg), "x"(arg));
+
+  // CHECK: pcmpestri
+  // CHECK-AVX: vpcmpestri
+}
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18698: [C11] PR24451: Allow restrict _Atomic pointers

2016-04-04 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla added a comment.

Richard, thank you for the review and explanation!
I don't have any examples of useful code using this extension, I was trying to 
fix the PR... So, do you think we should add this GCC extension to Clang (with 
a proper warning, of course) for compatibility reasons, or it will be better to 
close PR24451 and abandon this review?

Thank you,
Denis Zobnin


http://reviews.llvm.org/D18698



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18657: Propagate missing empty exception spec from function declared in system header

2016-04-08 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla added a comment.

Friendly ping, please take a look.

Thank you,
Denis Zobnin


http://reviews.llvm.org/D18657



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18700: [Inline asm][GCC compatibility] Handle %v-prefixed code in inline assembly

2016-04-12 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla updated this revision to Diff 53400.
d.zobnin.bugzilla added a comment.

Eric, thank you for the review!

I've renamed the test, but have also made it a .cpp file for the reasons 
described below.

You are right -- GCC looks at "target" attribute applied to the function in 
which inline asm exists. But GCC seems to take into account lambda's attributes 
as well, if asm statement is inside a lambda. To be correct, GCC seems to 
collect all target features from command line, function and lambda's 
attributes, so such code:

  void f8(void *x) __attribute__((__target__("no-avx")));
  void f8(void *x) {
auto g1 = [](void *arg) __attribute__((__target__("avx2"))) {
  auto g2 = [&arg]() __attribute__((__target__("no-mmx"))) {
int a = 10, b;
__asm__ ("%vmovq (%%rbp), %%xmm0" : "=r"(b) : "r"(a) : "%eax");
  };
  g2();
};
g1(x);
  }

will produce "vmovq" instruction regardless of command line arguments because 
of g1's attribute.

I tried several approaches to implement this behavior and came up with this 
patch, please take a look!


http://reviews.llvm.org/D18700

Files:
  include/clang/AST/Stmt.h
  lib/AST/Stmt.cpp
  lib/Sema/SemaStmtAsm.cpp
  test/CodeGen/avx-v-modifier-inline-asm.cpp

Index: lib/AST/Stmt.cpp
===
--- lib/AST/Stmt.cpp
+++ lib/AST/Stmt.cpp
@@ -632,6 +632,14 @@
 
   CurPtr = NameEnd+1;
   continue;
+} else if (*Begin == 'v') {
+  // GCC accepts code staring with "%v", e. g. "%vpcmpestri" and transforms
+  // it into "vpcmpestri" instruction if target processor supports AVX and
+  // into "pcmpestri" otherwise.
+  if (SupportsAVX)
+CurStringPiece = "v" + CurStringPiece;
+  CurStringPiece += EscapedChar;
+  continue;
 }
 
 DiagOffs = CurPtr-StrStart-1;
@@ -682,13 +690,15 @@
 //===--===//
 
 GCCAsmStmt::GCCAsmStmt(const ASTContext &C, SourceLocation asmloc,
-   bool issimple, bool isvolatile, unsigned numoutputs,
-   unsigned numinputs, IdentifierInfo **names,
-   StringLiteral **constraints, Expr **exprs,
-   StringLiteral *asmstr, unsigned numclobbers,
-   StringLiteral **clobbers, SourceLocation rparenloc)
-  : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
-numinputs, numclobbers), RParenLoc(rparenloc), AsmStr(asmstr) {
+   bool issimple, bool isvolatile, bool supportsavx,
+   unsigned numoutputs, unsigned numinputs,
+   IdentifierInfo **names, StringLiteral **constraints,
+   Expr **exprs, StringLiteral *asmstr,
+   unsigned numclobbers, StringLiteral **clobbers,
+   SourceLocation rparenloc)
+: AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
+  numinputs, numclobbers),
+  RParenLoc(rparenloc), AsmStr(asmstr), SupportsAVX(supportsavx) {
 
   unsigned NumExprs = NumOutputs + NumInputs;
 
Index: lib/Sema/SemaStmtAsm.cpp
===
--- lib/Sema/SemaStmtAsm.cpp
+++ lib/Sema/SemaStmtAsm.cpp
@@ -138,6 +138,75 @@
   return false;
 }
 
+// Collect all target features specified for the current context by the "target"
+// attribute. Start from current DeclContext and iterate its parents until we
+// find a function context.
+static void CollectTargetFeatures(Sema &S,
+  std::vector &TargetFeatures,
+  StringRef &TargetCPU) {
+  DeclContext *DC = S.CurContext;
+
+  auto Collect = [&TargetFeatures, &TargetCPU](const FunctionDecl *FD) {
+if (!FD)
+  return;
+if (const auto *TA = FD->getAttr()) {
+  TargetAttr::ParsedTargetAttr ParsedAttr = TA->parse();
+  TargetFeatures.insert(TargetFeatures.begin(), ParsedAttr.first.begin(),
+ParsedAttr.first.end());
+  if (TargetCPU == "")
+TargetCPU = ParsedAttr.second;
+}
+  };
+
+  // Climb up the tree of nested DeclContext-s, collecting the target features.
+  while (true) {
+if (isa(DC) || isa(DC) || isa(DC)) {
+  DC = DC->getParent();
+} else if (const auto *MD = dyn_cast(DC)) {
+  // Check if it's a lambda and collect its target features.
+  if (MD->getOverloadedOperator() == OO_Call &&
+  cast(DC->getParent())->isLambda()) {
+Collect(MD);
+  }
+  DC = DC->getParent()->getParent();
+} else {
+  // It's the nearest function, collect its features and break.
+  Collect(dyn_cast(DC));
+  break;
+}
+  }
+}
+
+// Check whether a particular target feature is enabled in current context,
+// either by command-line options or by __attribute__((__target__("..."))),
+// applied to any surrounding lambda or func

Re: [PATCH] D18657: Propagate missing empty exception spec from function declared in system header

2016-04-12 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla updated this revision to Diff 53414.
d.zobnin.bugzilla added a comment.

John, thanks for the review!

Please take a look at the updated patch -- did I understand your comments 
correctly?
The test passes and ds2 application is compiled successfully.

Thank you,
Denis Zobnin


http://reviews.llvm.org/D18657

Files:
  lib/Sema/SemaExceptionSpec.cpp
  test/SemaCXX/Inputs/malloc.h
  test/SemaCXX/builtin-exception-spec.cpp

Index: lib/Sema/SemaExceptionSpec.cpp
===
--- lib/Sema/SemaExceptionSpec.cpp
+++ lib/Sema/SemaExceptionSpec.cpp
@@ -254,10 +254,10 @@
   // to many libc functions as an optimization. Unfortunately, that
   // optimization isn't permitted by the C++ standard, so we're forced
   // to work around it here.
-  if (MissingEmptyExceptionSpecification && NewProto &&
-  (Old->getLocation().isInvalid() ||
-   Context.getSourceManager().isInSystemHeader(Old->getLocation())) &&
-  Old->isExternC()) {
+  FunctionDecl *First = Old->getFirstDecl();
+  if (MissingEmptyExceptionSpecification && NewProto && First->isExternC() &&
+  (First->getLocation().isInvalid() ||
+   Context.getSourceManager().isInSystemHeader(First->getLocation( {
 New->setType(Context.getFunctionType(
 NewProto->getReturnType(), NewProto->getParamTypes(),
 NewProto->getExtProtoInfo().withExceptionSpec(EST_DynamicNone)));
Index: test/SemaCXX/builtin-exception-spec.cpp
===
--- test/SemaCXX/builtin-exception-spec.cpp
+++ test/SemaCXX/builtin-exception-spec.cpp
@@ -4,4 +4,7 @@
 
 extern "C" {
 void *malloc(__SIZE_TYPE__);
+
+void MyFunc() __attribute__((__weak__));
+void MyFunc() { return; }
 }
Index: test/SemaCXX/Inputs/malloc.h
===
--- test/SemaCXX/Inputs/malloc.h
+++ test/SemaCXX/Inputs/malloc.h
@@ -1,3 +1,5 @@
 extern "C" {
 extern void *malloc (__SIZE_TYPE__ __size) throw () __attribute__ 
((__malloc__)) ;
+
+void MyFunc() throw();
 }


Index: lib/Sema/SemaExceptionSpec.cpp
===
--- lib/Sema/SemaExceptionSpec.cpp
+++ lib/Sema/SemaExceptionSpec.cpp
@@ -254,10 +254,10 @@
   // to many libc functions as an optimization. Unfortunately, that
   // optimization isn't permitted by the C++ standard, so we're forced
   // to work around it here.
-  if (MissingEmptyExceptionSpecification && NewProto &&
-  (Old->getLocation().isInvalid() ||
-   Context.getSourceManager().isInSystemHeader(Old->getLocation())) &&
-  Old->isExternC()) {
+  FunctionDecl *First = Old->getFirstDecl();
+  if (MissingEmptyExceptionSpecification && NewProto && First->isExternC() &&
+  (First->getLocation().isInvalid() ||
+   Context.getSourceManager().isInSystemHeader(First->getLocation( {
 New->setType(Context.getFunctionType(
 NewProto->getReturnType(), NewProto->getParamTypes(),
 NewProto->getExtProtoInfo().withExceptionSpec(EST_DynamicNone)));
Index: test/SemaCXX/builtin-exception-spec.cpp
===
--- test/SemaCXX/builtin-exception-spec.cpp
+++ test/SemaCXX/builtin-exception-spec.cpp
@@ -4,4 +4,7 @@
 
 extern "C" {
 void *malloc(__SIZE_TYPE__);
+
+void MyFunc() __attribute__((__weak__));
+void MyFunc() { return; }
 }
Index: test/SemaCXX/Inputs/malloc.h
===
--- test/SemaCXX/Inputs/malloc.h
+++ test/SemaCXX/Inputs/malloc.h
@@ -1,3 +1,5 @@
 extern "C" {
 extern void *malloc (__SIZE_TYPE__ __size) throw () __attribute__ ((__malloc__)) ;
+
+void MyFunc() throw();
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18652: [Inline asm] Correctly parse GCC-style asm line following MS-style asm line

2016-04-13 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla added a reviewer: rsmith.
d.zobnin.bugzilla removed a subscriber: rsmith.
d.zobnin.bugzilla updated this revision to Diff 53543.
d.zobnin.bugzilla added a comment.

Richard, thank you for the review!

I've created a static function to check if this is a GCC asm statement as you 
recommended to do, and also made "isTypeQualifier" function static.
I've added a check for "goto" after "asm" to treat such statements as GCC-style 
assembly.
Also, do you think it will be better to diagnose unsupported "asm goto" 
statements rather than fall into parsing them and emit "expected identifier" 
error or something like that?

Thank you,
Denis Zobnin


http://reviews.llvm.org/D18652

Files:
  include/clang/Basic/DiagnosticParseKinds.td
  include/clang/Parse/Parser.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseStmtAsm.cpp
  test/CodeGen/inline-asm-mixed-style.c

Index: lib/Parse/ParseStmtAsm.cpp
===
--- lib/Parse/ParseStmtAsm.cpp
+++ lib/Parse/ParseStmtAsm.cpp
@@ -335,6 +335,33 @@
   return false;
 }
 
+/// isTypeQualifier - Return true if the current token could be the
+/// start of a type-qualifier-list.
+static bool isTypeQualifier(const Token &Tok) {
+  switch (Tok.getKind()) {
+  default: return false;
+  // type-qualifier
+  case tok::kw_const:
+  case tok::kw_volatile:
+  case tok::kw_restrict:
+  case tok::kw___private:
+  case tok::kw___local:
+  case tok::kw___global:
+  case tok::kw___constant:
+  case tok::kw___generic:
+  case tok::kw___read_only:
+  case tok::kw___read_write:
+  case tok::kw___write_only:
+return true;
+  }
+}
+
+// Determine if this is a GCC-style asm statement.
+static bool isGCCAsmStatement(const Token &TokAfterAsm) {
+  return TokAfterAsm.is(tok::l_paren) || TokAfterAsm.is(tok::kw_goto) ||
+ isTypeQualifier(TokAfterAsm);
+}
+
 /// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled,
 /// this routine is called to collect the tokens for an MS asm statement.
 ///
@@ -415,11 +442,11 @@
   if (ExpLoc.first != FID ||
   SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second) != LineNo) {
 // If this is a single-line __asm, we're done, except if the next
-// line begins with an __asm too, in which case we finish a comment
+// line is MS-style asm too, in which case we finish a comment
 // if needed and then keep processing the next line as a single
 // line __asm.
 bool isAsm = Tok.is(tok::kw_asm);
-if (SingleLineMode && !isAsm)
+if (SingleLineMode && (!isAsm || isGCCAsmStatement(NextToken(
   break;
 // We're no longer in a comment.
 InAsmComment = false;
@@ -643,8 +670,7 @@
   assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
   SourceLocation AsmLoc = ConsumeToken();
 
-  if (getLangOpts().AsmBlocks && Tok.isNot(tok::l_paren) &&
-  !isTypeQualifier()) {
+  if (getLangOpts().AsmBlocks && !isGCCAsmStatement(Tok)) {
 msAsm = true;
 return ParseMicrosoftAsmStatement(AsmLoc);
   }
@@ -664,6 +690,14 @@
 
   // Remember if this was a volatile asm.
   bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile;
+
+  // TODO: support "asm goto" constructs (PR#9295).
+  if (Tok.is(tok::kw_goto)) {
+Diag(Tok, diag::err_asm_goto_not_supported_yet);
+SkipUntil(tok::r_paren, StopAtSemi);
+return StmtError();
+  }
+
   if (Tok.isNot(tok::l_paren)) {
 Diag(Tok, diag::err_expected_lparen_after) << "asm";
 SkipUntil(tok::r_paren, StopAtSemi);
Index: lib/Parse/ParseDecl.cpp
===
--- lib/Parse/ParseDecl.cpp
+++ lib/Parse/ParseDecl.cpp
@@ -4259,27 +4259,6 @@
   }
 }
 
-/// isTypeSpecifierQualifier - Return true if the current token could be the
-/// start of a type-qualifier-list.
-bool Parser::isTypeQualifier() const {
-  switch (Tok.getKind()) {
-  default: return false;
-  // type-qualifier
-  case tok::kw_const:
-  case tok::kw_volatile:
-  case tok::kw_restrict:
-  case tok::kw___private:
-  case tok::kw___local:
-  case tok::kw___global:
-  case tok::kw___constant:
-  case tok::kw___generic:
-  case tok::kw___read_only:
-  case tok::kw___read_write:
-  case tok::kw___write_only:
-return true;
-  }
-}
-
 /// isKnownToBeTypeSpecifier - Return true if we know that the specified token
 /// is definitely a type-specifier.  Return false if it isn't part of a type
 /// specifier or if we're not sure.
Index: include/clang/Parse/Parser.h
===
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -1873,7 +1873,6 @@
 
   bool isDeclarationSpecifier(bool DisambiguatingWithExpression = false);
   bool isTypeSpecifierQualifier();
-  bool isTypeQualifier() const;
 
   /// isKnownToBeTypeSpecifier - Return true if we know that the specified token
   /// is definitely a type-specifier.  Return false if it isn't part of a type
Index: i

Re: [PATCH] D18698: [C11] PR24451: Allow restrict _Atomic pointers

2016-04-14 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla added a comment.

Richard, please let me know what in your opinion we should do with this 
revision.

Thank you,
Denis Zobnin


http://reviews.llvm.org/D18698



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18700: [Inline asm][GCC compatibility] Handle %v-prefixed code in inline assembly

2016-04-19 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla marked an inline comment as done.
d.zobnin.bugzilla added a comment.

Friendly ping, please take a look.

Thank you,
Denis Zobnin


http://reviews.llvm.org/D18700



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18657: Propagate missing empty exception spec from function declared in system header

2016-04-19 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla added a comment.

Friendly ping, please take a look.

Thank you,
Denis Zobnin


http://reviews.llvm.org/D18657



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18652: [Inline asm] Correctly parse GCC-style asm line following MS-style asm line

2016-04-20 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla added a comment.

Richard, Eric,

Please take a look at the patch.

Thank you,
Denis Zobnin


http://reviews.llvm.org/D18652



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r266976 - Correctly parse GCC-style asm line following MS-style asm line.

2016-04-21 Thread Denis Zobnin via cfe-commits
Author: dzobnin
Date: Thu Apr 21 05:59:18 2016
New Revision: 266976

URL: http://llvm.org/viewvc/llvm-project?rev=266976&view=rev
Log:
Correctly parse GCC-style asm line following MS-style asm line.

Quit parsing MS-style inline assembly if the following statement has GCC style.
Enables compilation of code like

void f() {
  __asm mov ebx, ecx
  __asm__("movl %ecx, %edx");
}

Differential Revision: http://reviews.llvm.org/D18652

Added:
cfe/trunk/test/CodeGen/inline-asm-mixed-style.c   (with props)
Modified:
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseStmtAsm.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=266976&r1=266975&r2=266976&view=diff
==
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Thu Apr 21 05:59:18 
2016
@@ -27,6 +27,8 @@ def err_msasm_unable_to_create_target :
   "MS-style inline assembly is not available: %0">;
 def err_gnu_inline_asm_disabled : Error<
   "GNU-style inline assembly is disabled">;
+def err_asm_goto_not_supported_yet : Error<
+  "'asm goto' constructs are not supported yet">;
 }
 
 let CategoryName = "Parse Issue" in {

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=266976&r1=266975&r2=266976&view=diff
==
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Thu Apr 21 05:59:18 2016
@@ -1873,7 +1873,6 @@ private:
 
   bool isDeclarationSpecifier(bool DisambiguatingWithExpression = false);
   bool isTypeSpecifierQualifier();
-  bool isTypeQualifier() const;
 
   /// isKnownToBeTypeSpecifier - Return true if we know that the specified 
token
   /// is definitely a type-specifier.  Return false if it isn't part of a type

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=266976&r1=266975&r2=266976&view=diff
==
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Apr 21 05:59:18 2016
@@ -4255,27 +4255,6 @@ void Parser::ParseEnumBody(SourceLocatio
   }
 }
 
-/// isTypeSpecifierQualifier - Return true if the current token could be the
-/// start of a type-qualifier-list.
-bool Parser::isTypeQualifier() const {
-  switch (Tok.getKind()) {
-  default: return false;
-  // type-qualifier
-  case tok::kw_const:
-  case tok::kw_volatile:
-  case tok::kw_restrict:
-  case tok::kw___private:
-  case tok::kw___local:
-  case tok::kw___global:
-  case tok::kw___constant:
-  case tok::kw___generic:
-  case tok::kw___read_only:
-  case tok::kw___read_write:
-  case tok::kw___write_only:
-return true;
-  }
-}
-
 /// isKnownToBeTypeSpecifier - Return true if we know that the specified token
 /// is definitely a type-specifier.  Return false if it isn't part of a type
 /// specifier or if we're not sure.

Modified: cfe/trunk/lib/Parse/ParseStmtAsm.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmtAsm.cpp?rev=266976&r1=266975&r2=266976&view=diff
==
--- cfe/trunk/lib/Parse/ParseStmtAsm.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmtAsm.cpp Thu Apr 21 05:59:18 2016
@@ -335,6 +335,33 @@ static bool buildMSAsmString(Preprocesso
   return false;
 }
 
+/// isTypeQualifier - Return true if the current token could be the
+/// start of a type-qualifier-list.
+static bool isTypeQualifier(const Token &Tok) {
+  switch (Tok.getKind()) {
+  default: return false;
+  // type-qualifier
+  case tok::kw_const:
+  case tok::kw_volatile:
+  case tok::kw_restrict:
+  case tok::kw___private:
+  case tok::kw___local:
+  case tok::kw___global:
+  case tok::kw___constant:
+  case tok::kw___generic:
+  case tok::kw___read_only:
+  case tok::kw___read_write:
+  case tok::kw___write_only:
+return true;
+  }
+}
+
+// Determine if this is a GCC-style asm statement.
+static bool isGCCAsmStatement(const Token &TokAfterAsm) {
+  return TokAfterAsm.is(tok::l_paren) || TokAfterAsm.is(tok::kw_goto) ||
+ isTypeQualifier(TokAfterAsm);
+}
+
 /// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled,
 /// this routine is called to collect the tokens for an MS asm statement.
 ///
@@ -415,11 +442,11 @@ StmtResult Parser::ParseMicrosoftAsmStat
   if (ExpLoc.first != FID ||
   SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second) != LineNo) {
 // If this is a single-line __asm, we're done, except if the nex

[PATCH] D19361: [MS] Improved implementation of MS stack pragmas (vtordisp, *_seg)

2016-04-21 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla created this revision.
d.zobnin.bugzilla added a reviewer: rnk.
d.zobnin.bugzilla added a subscriber: cfe-commits.

This patch attempts to improve implementation of several MS pragmas that use 
stack (vtordisp, { bss | code | const | data }_seg) and fix some compatibility 
issues.
Please take a look at the patch and let me know whether it's something worth 
working on and whether I'm on the right way of doing this.

This patch:
1. Changes implementation of #pragma vtordisp to use existing PragmaStack<> 
template class that *_seg pragmas use;
2. Fixes "#pragma vtordisp()" reset behavior -- it shouldn't affect the stack;
3. Supports "save-and-restore" of pragma state stacks on entering / exiting a 
C++ method body, as MSVC does.

If this work is accepted, I propose several to-do's:
1. Change #pragma pack implementation to use the same approach as other "stack" 
pragmas use;
2. Introduce diagnostics on popping named stack slots, as MSVC does

Currently I tried to make Clang behave exactly as MSVC behaves, though, I can 
think of possible better solutions, please see "Implementation notes" below.


Motivation:

Currently Clang implements "stack" pragmas in several ways: "vtordisp" and 
"pack" have their own stacks in Sema, pragma actions are performed differently.

MSVC seems to have a common implementation of all these pragmas. One common 
feature is "save-restore" on entering / exiting a C++ method body:
```
#pragma pack(4)
#pragma pack(show)

struct S {
  void f() {
#pragma pack(push, 8)
#pragma pack(show)
  }
};

#pragma pack(show)
```
MSVC's output: 4, 8, 4
Clang's output:  4, 8, 8

MSVC seems to introduce artificial sentinel slots on entering a C++ method body 
and pops them on exit. Consider
```
#pragma pack(push, 4)
struct S {
  void f() {
#pragma pack(pop)
  }
};
```
MSVC emits:
```
warning C4159: #pragma vtordisp(pop,...): has popped previously pushed 
identifier ''
```
The same approach is used for "vtordisp" pragma, although it doesn't support 
#pragma vtordisp (pop, id) syntax.
Please note that in the above example the stack gets corrupted and might lead 
to unexpected behavior later.

I implemented "save-and-restore" feature for #pragma vtordisp in 
http://reviews.llvm.org/D14467 by copying a skack to a RAII object and back, no 
matter how many times "pop" is used. Pragmas other than "vtordisp" in Clang 
don't support this feature yet.


Implementation notes:

MSVC seems to use the same name "" even for methods of 
nested classes. It is legal in correct cases, because "#pragma (pop, id)" 
will look for the closest slot with mathing name, but if the nested sentinel 
slot is mistakenly popped, it will cause popping the stack up to surrounding 
sentinel.
Maybe, if we choose this approach, we could use unique sentinel names for 
better recovery? Or even mark the sentinels to prevent a programmer from 
popping them by accident?

http://reviews.llvm.org/D19361

Files:
  include/clang/Sema/Sema.h
  lib/Parse/ParsePragma.cpp
  lib/Parse/ParseStmt.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaAttr.cpp
  test/CodeGenCXX/sections.cpp
  test/SemaCXX/pragma-vtordisp.cpp

Index: lib/Parse/ParseStmt.cpp
===
--- lib/Parse/ParseStmt.cpp
+++ lib/Parse/ParseStmt.cpp
@@ -1928,7 +1928,8 @@
   // Save and reset current vtordisp stack if we have entered a C++ method body.
   bool IsCXXMethod =
   getLangOpts().CPlusPlus && Decl && isa(Decl);
-  Sema::VtorDispStackRAII SavedVtorDispStack(Actions, IsCXXMethod);
+  Sema::PragmaStackSentinelRAII
+PragmaStackSentinel(Actions, "InternalPragmaState", IsCXXMethod);
 
   // Do not enter a scope for the brace, as the arguments are in the same scope
   // (the function body) as the body itself.  Instead, just read the statement
@@ -1972,7 +1973,8 @@
   // Save and reset current vtordisp stack if we have entered a C++ method body.
   bool IsCXXMethod =
   getLangOpts().CPlusPlus && Decl && isa(Decl);
-  Sema::VtorDispStackRAII SavedVtorDispStack(Actions, IsCXXMethod);
+  Sema::PragmaStackSentinelRAII
+PragmaStackSentinel(Actions, "InternalPragmaState", IsCXXMethod);
 
   SourceLocation LBraceLoc = Tok.getLocation();
   StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc, /*FnTry*/true));
Index: lib/Parse/ParsePragma.cpp
===
--- lib/Parse/ParsePragma.cpp
+++ lib/Parse/ParsePragma.cpp
@@ -497,11 +497,11 @@
 void Parser::HandlePragmaMSVtorDisp() {
   assert(Tok.is(tok::annot_pragma_ms_vtordisp));
   uintptr_t Value = reinterpret_cast(Tok.getAnnotationValue());
-  Sema::PragmaVtorDispKind Kind =
-  static_cast((Value >> 16) & 0x);
+  Sema::PragmaMsStackAction Action =
+  static_cast((Value >> 16) & 0x);
   MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0x);
   SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
-  Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode);
+  Actions.A

r270686 - [ms][dll] #26935 Defining a dllimport function should cause it to be exported

2016-05-25 Thread Denis Zobnin via cfe-commits
Author: dzobnin
Date: Wed May 25 06:32:42 2016
New Revision: 270686

URL: http://llvm.org/viewvc/llvm-project?rev=270686&view=rev
Log:
[ms][dll] #26935 Defining a dllimport function should cause it to be exported

If we have some function with dllimport attribute and then we have the function
definition in the same module but without dllimport attribute we should add
dllexport attribute to this function definition.
The same should be done for variables.

Example:
struct __declspec(dllimport) C3 {
  ~C3();
};
C3::~C3() {;} // we should export this definition.

Patch by Andrew V. Tischenko

Differential revision: http://reviews.llvm.org/D18953

Modified:
cfe/trunk/include/clang/Basic/DiagnosticGroups.td
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/CodeGen/dllimport.c
cfe/trunk/test/CodeGenCXX/dllimport-members.cpp
cfe/trunk/test/CodeGenCXX/dllimport.cpp
cfe/trunk/test/Sema/dllimport.c
cfe/trunk/test/SemaCXX/dllimport.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=270686&r1=270685&r2=270686&view=diff
==
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Wed May 25 06:32:42 2016
@@ -772,6 +772,7 @@ def MicrosoftEnumValue : DiagGroup<"micr
 def MicrosoftDefaultArgRedefinition :
 DiagGroup<"microsoft-default-arg-redefinition">;
 def MicrosoftTemplate : DiagGroup<"microsoft-template">;
+def MicrosoftInconsistentDllImport : DiagGroup<"inconsistent-dllimport">;
 def MicrosoftRedeclareStatic : DiagGroup<"microsoft-redeclare-static">;
 def MicrosoftEnumForwardReference :
 DiagGroup<"microsoft-enum-forward-reference">;
@@ -798,7 +799,8 @@ def Microsoft : DiagGroup<"microsoft",
  MicrosoftRedeclareStatic, MicrosoftEnumForwardReference, MicrosoftGoto,
  MicrosoftFlexibleArray, MicrosoftExtraQualification, MicrosoftCast,
  MicrosoftConstInit, MicrosoftVoidPseudoDtor, MicrosoftAnonTag,
- MicrosoftCommentPaste, MicrosoftEndOfFile]>;
+ MicrosoftCommentPaste, MicrosoftEndOfFile,
+ MicrosoftInconsistentDllImport]>;
 
 def ClangClPch : DiagGroup<"clang-cl-pch">;
 

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=270686&r1=270685&r2=270686&view=diff
==
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed May 25 06:32:42 
2016
@@ -2359,7 +2359,10 @@ def err_attribute_aligned_too_great : Er
   "requested alignment must be %0 bytes or smaller">;
 def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning<
   "%q0 redeclared without %1 attribute: previous %1 ignored">,
-  InGroup>;
+  InGroup;
+def warn_redeclaration_without_import_attribute : Warning<
+  "%q0 redeclared without 'dllimport' attribute: 'dllexport' attribute added">,
+  InGroup;
 def warn_dllimport_dropped_from_inline_function : Warning<
   "%q0 redeclared inline; %1 attribute ignored">,
   InGroup;

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=270686&r1=270685&r2=270686&view=diff
==
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed May 25 06:32:42 2016
@@ -5559,9 +5559,13 @@ static void checkAttributesAfterMerging(
 
 static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
NamedDecl *NewDecl,
-   bool IsSpecialization) {
-  if (TemplateDecl *OldTD = dyn_cast(OldDecl))
+   bool IsSpecialization,
+   bool IsDefinition) {
+  if (TemplateDecl *OldTD = dyn_cast(OldDecl)) {
 OldDecl = OldTD->getTemplatedDecl();
+if (!IsSpecialization)
+  IsDefinition = false;
+  }
   if (TemplateDecl *NewTD = dyn_cast(NewDecl))
 NewDecl = NewTD->getTemplatedDecl();
 
@@ -5617,14 +5621,17 @@ static void checkDLLAttributeRedeclarati
 
   // A redeclaration is not allowed to drop a dllimport attribute, the only
   // exceptions being inline function definitions, local extern declarations,
-  // and qualified friend declarations.
-  // NB: MSVC converts such a declaration to dllexport.
+  // qualified friend declarations or special MSVC extension: in the last case,
+  // the declaration is treated as if it were marked dllexport.
   bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false;
-  if (const auto *VD = dyn_cast(NewDecl))
+  bool IsMicrosoft 

[PATCH] D16112: PR26111: segmentation fault with __attribute__((mode(QI))) on function declaration

2016-01-12 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla created this revision.
d.zobnin.bugzilla added a reviewer: aaron.ballman.
d.zobnin.bugzilla added a subscriber: cfe-commits.

Allow "mode" attribute to be applied to VarDecl, not ValueDecl (which includes 
FunctionDecl and EnumConstantDecl), emit an error if this attribute is used 
with function declarations and enum constants.

http://reviews.llvm.org/D16112

Files:
  include/clang/AST/Decl.h
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaDeclAttr.cpp
  test/Sema/attr-mode.c

Index: lib/Sema/SemaDeclAttr.cpp
===
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -3372,11 +3372,11 @@
   QualType OldTy;
   if (TypedefNameDecl *TD = dyn_cast(D))
 OldTy = TD->getUnderlyingType();
-  else if (ValueDecl *VD = dyn_cast(D))
+  else if (VarDecl *VD = dyn_cast(D))
 OldTy = VD->getType();
   else {
-S.Diag(D->getLocation(), diag::err_attr_wrong_decl)
-  << Attr.getName() << Attr.getRange();
+S.Diag(D->getLocation(), diag::err_mode_requires_typedef_or_variable)
+<< Attr.getRange();
 return;
   }
 
@@ -3451,7 +3451,7 @@
   if (TypedefNameDecl *TD = dyn_cast(D))
 TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy);
   else
-cast(D)->setType(NewTy);
+cast(D)->setType(NewTy);
 
   D->addAttr(::new (S.Context)
  ModeAttr(Attr.getRange(), S.Context, Name,
Index: include/clang/AST/Decl.h
===
--- include/clang/AST/Decl.h
+++ include/clang/AST/Decl.h
@@ -1954,6 +1954,7 @@
   unsigned getMinRequiredArguments() const;
 
   QualType getReturnType() const {
+assert(getType()->getAs() && "Expected a FunctionType!");
 return getType()->getAs()->getReturnType();
   }
 
@@ -1964,6 +1965,7 @@
 
   /// \brief Determine the type of an expression that calls this function.
   QualType getCallResultType() const {
+assert(getType()->getAs() && "Expected a FunctionType!");
 return 
getType()->getAs()->getCallResultType(getASTContext());
   }
 
Index: include/clang/Basic/DiagnosticSemaKinds.td
===
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -2838,14 +2838,14 @@
   "mode attribute only supported for integer and floating-point types">;
 def err_mode_wrong_type : Error<
   "type of machine mode does not match type of base type">;
+def err_mode_requires_typedef_or_variable : Error<
+  "mode attribute invalid on this declaration, requires typedef or variable">;
 def warn_vector_mode_deprecated : Warning<
   "specifying vector types with the 'mode' attribute is deprecated; "
   "use the 'vector_size' attribute instead">,
   InGroup;
 def err_complex_mode_vector_type : Error<
   "type of machine mode does not support base vector types">;
-def err_attr_wrong_decl : Error<
-  "%0 attribute invalid on this declaration, requires typedef or value">;
 def warn_attribute_nonnull_no_pointers : Warning<
   "'nonnull' attribute applied to function with no pointer arguments">,
   InGroup;
Index: test/Sema/attr-mode.c
===
--- test/Sema/attr-mode.c
+++ test/Sema/attr-mode.c
@@ -24,6 +24,9 @@
 
 int **__attribute((mode(QI)))* i32;  // expected-error{{mode attribute}}
 
+__attribute__((mode(QI))) int invalid_func() { return 1; } // 
expected-error{{mode attribute invalid on this declaration}}
+enum invalid_enum { A1 __attribute__((mode(QI))) }; // expected-error{{mode 
attribute invalid on this declaration}}
+
 typedef _Complex double c32 __attribute((mode(SC)));
 int c32_test[sizeof(c32) == 8 ? 1 : -1];
 typedef _Complex float c64 __attribute((mode(DC)));


Index: lib/Sema/SemaDeclAttr.cpp
===
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -3372,11 +3372,11 @@
   QualType OldTy;
   if (TypedefNameDecl *TD = dyn_cast(D))
 OldTy = TD->getUnderlyingType();
-  else if (ValueDecl *VD = dyn_cast(D))
+  else if (VarDecl *VD = dyn_cast(D))
 OldTy = VD->getType();
   else {
-S.Diag(D->getLocation(), diag::err_attr_wrong_decl)
-  << Attr.getName() << Attr.getRange();
+S.Diag(D->getLocation(), diag::err_mode_requires_typedef_or_variable)
+<< Attr.getRange();
 return;
   }
 
@@ -3451,7 +3451,7 @@
   if (TypedefNameDecl *TD = dyn_cast(D))
 TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy);
   else
-cast(D)->setType(NewTy);
+cast(D)->setType(NewTy);
 
   D->addAttr(::new (S.Context)
  ModeAttr(Attr.getRange(), S.Context, Name,
Index: include/clang/AST/Decl.h
===
--- include/clang/AST/Decl.h
+++ include/clang/AST/Decl.h
@@ -1954,6 +1954,7 @@
   unsigned getMinRequiredArguments() const;
 
   QualType getReturnType() const {
+assert(getType()->getA

Re: [PATCH] D16112: PR26111: segmentation fault with __attribute__((mode(QI))) on function declaration

2016-01-14 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla updated this revision to Diff 44859.
d.zobnin.bugzilla added a comment.

Thanks for the review! Updated the patch: added Subjects line for the attribute 
and removed the "err_attr_wrong_decl" diagnostics.


http://reviews.llvm.org/D16112

Files:
  include/clang/AST/Decl.h
  include/clang/Basic/Attr.td
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaDeclAttr.cpp
  test/Sema/attr-mode.c

Index: lib/Sema/SemaDeclAttr.cpp
===
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -3391,13 +3391,8 @@
   QualType OldTy;
   if (TypedefNameDecl *TD = dyn_cast(D))
 OldTy = TD->getUnderlyingType();
-  else if (ValueDecl *VD = dyn_cast(D))
-OldTy = VD->getType();
-  else {
-S.Diag(D->getLocation(), diag::err_attr_wrong_decl)
-  << Attr.getName() << Attr.getRange();
-return;
-  }
+  else
+OldTy = cast(D)->getType();
 
   // Base type can also be a vector type (see PR17453).
   // Distinguish between base type and base element type.
@@ -3470,7 +3465,7 @@
   if (TypedefNameDecl *TD = dyn_cast(D))
 TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy);
   else
-cast(D)->setType(NewTy);
+cast(D)->setType(NewTy);
 
   D->addAttr(::new (S.Context)
  ModeAttr(Attr.getRange(), S.Context, Name,
Index: include/clang/AST/Decl.h
===
--- include/clang/AST/Decl.h
+++ include/clang/AST/Decl.h
@@ -1954,6 +1954,7 @@
   unsigned getMinRequiredArguments() const;
 
   QualType getReturnType() const {
+assert(getType()->getAs() && "Expected a FunctionType!");
 return getType()->getAs()->getReturnType();
   }
 
@@ -1964,6 +1965,7 @@
 
   /// \brief Determine the type of an expression that calls this function.
   QualType getCallResultType() const {
+assert(getType()->getAs() && "Expected a FunctionType!");
 return 
getType()->getAs()->getCallResultType(getASTContext());
   }
 
Index: include/clang/Basic/DiagnosticSemaKinds.td
===
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -2844,8 +2844,6 @@
   InGroup;
 def err_complex_mode_vector_type : Error<
   "type of machine mode does not support base vector types">;
-def err_attr_wrong_decl : Error<
-  "%0 attribute invalid on this declaration, requires typedef or value">;
 def warn_attribute_nonnull_no_pointers : Warning<
   "'nonnull' attribute applied to function with no pointer arguments">,
   InGroup;
Index: include/clang/Basic/Attr.td
===
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -878,6 +878,8 @@
 
 def Mode : Attr {
   let Spellings = [GCC<"mode">];
+  let Subjects = SubjectList<[Var, TypedefName], ErrorDiag,
+ "ExpectedVariableOrTypedef">;
   let Args = [IdentifierArgument<"Mode">];
   let Documentation = [Undocumented];
 }
Index: test/Sema/attr-mode.c
===
--- test/Sema/attr-mode.c
+++ test/Sema/attr-mode.c
@@ -24,6 +24,9 @@
 
 int **__attribute((mode(QI)))* i32;  // expected-error{{mode attribute}}
 
+__attribute__((mode(QI))) int invalid_func() { return 1; } // 
expected-error{{'mode' attribute only applies to variables and typedefs}}
+enum invalid_enum { A1 __attribute__((mode(QI))) }; // expected-error{{'mode' 
attribute only applies to variables and typedefs}}
+
 typedef _Complex double c32 __attribute((mode(SC)));
 int c32_test[sizeof(c32) == 8 ? 1 : -1];
 typedef _Complex float c64 __attribute((mode(DC)));


Index: lib/Sema/SemaDeclAttr.cpp
===
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -3391,13 +3391,8 @@
   QualType OldTy;
   if (TypedefNameDecl *TD = dyn_cast(D))
 OldTy = TD->getUnderlyingType();
-  else if (ValueDecl *VD = dyn_cast(D))
-OldTy = VD->getType();
-  else {
-S.Diag(D->getLocation(), diag::err_attr_wrong_decl)
-  << Attr.getName() << Attr.getRange();
-return;
-  }
+  else
+OldTy = cast(D)->getType();
 
   // Base type can also be a vector type (see PR17453).
   // Distinguish between base type and base element type.
@@ -3470,7 +3465,7 @@
   if (TypedefNameDecl *TD = dyn_cast(D))
 TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy);
   else
-cast(D)->setType(NewTy);
+cast(D)->setType(NewTy);
 
   D->addAttr(::new (S.Context)
  ModeAttr(Attr.getRange(), S.Context, Name,
Index: include/clang/AST/Decl.h
===
--- include/clang/AST/Decl.h
+++ include/clang/AST/Decl.h
@@ -1954,6 +1954,7 @@
   unsigned getMinRequiredArguments() const;
 
   QualType getReturnType() const {
+assert(getType()->getAs() && "Expected a FunctionType!");
 return getType()-

[PATCH] D16216: Fix infinite loop when ::new or ::delete are found in member initializer list

2016-01-15 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla created this revision.
d.zobnin.bugzilla added reviewers: kcc, rsmith.
d.zobnin.bugzilla added a subscriber: cfe-commits.

Fix for a case found by fuzzing PR23057 (comment #33 
https://llvm.org/bugs/show_bug.cgi?id=23057#c33). Diagnose and consume 
unexpected ::new and ::delete tokens to prevent infinite loop in parsing a 
member initializer list.

http://reviews.llvm.org/D16216

Files:
  include/clang/Basic/DiagnosticParseKinds.td
  lib/Parse/ParseDeclCXX.cpp
  test/Parser/cxx-invalid-function-decl.cpp

Index: lib/Parse/ParseDeclCXX.cpp
===
--- lib/Parse/ParseDeclCXX.cpp
+++ lib/Parse/ParseDeclCXX.cpp
@@ -3237,6 +3237,20 @@
   CXXScopeSpec SS;
   ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
   ParsedType TemplateTypeTy;
+  // If ::new or ::delete was met, ParseOptionalCXXScopeSpecifier just left
+  // them untouched. Diagnose it now to prevent infinite loop on parsing such
+  // code: "f() : ::new".
+  if (Tok.is(tok::coloncolon)) {
+tok::TokenKind NextKind = NextToken().getKind();
+if (NextKind == tok::kw_new || NextKind == tok::kw_delete) {
+  SourceRange Range(Tok.getLocation(), NextToken().getEndLoc());
+  Diag(Tok.getLocation(), diag::err_unexpected_in_member_initlist)
+  << (NextKind == tok::kw_delete) << Range;
+  ConsumeToken(); // the '::' token.
+  ConsumeToken(); // 'new' or 'delete'.
+  return true;
+}
+  }
   if (Tok.is(tok::annot_template_id)) {
 TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
 if (TemplateId->Kind == TNK_Type_template ||
Index: include/clang/Basic/DiagnosticParseKinds.td
===
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -161,6 +161,8 @@
 def err_at_defs_cxx : Error<"@defs is not supported in Objective-C++">;
 def err_at_in_class : Error<"unexpected '@' in member specification">;
 def err_unexpected_semi : Error<"unexpected ';' before %0">;
+def err_unexpected_in_member_initlist : Error<
+  "unexpected %select{'::new'|'::delete'}0 in member initializer list">;
 
 def err_expected_fn_body : Error<
   "expected function body after function declarator">;
Index: test/Parser/cxx-invalid-function-decl.cpp
===
--- test/Parser/cxx-invalid-function-decl.cpp
+++ test/Parser/cxx-invalid-function-decl.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+void f() : X() ::new{}; // expected-error{{missing ',' between base or member 
initializers}}
+// expected-error@-1{{unexpected '::new' in member 
initializer list}}
+// expected-error@-2{{only constructors take base 
initializers}}
+
+template 
+struct Base1 {
+  T x1;
+  Base1(T a1) : x1(a1) {}
+};
+
+template 
+struct Base2 {
+  T x2;
+  Base2(T a2) : x2(a2) {}
+};
+
+struct S : public Base1, public Base2 {
+  int x;
+  S() : ::Base1(0) ::new, ::Base2(1.0) ::delete x(2) {} // 
expected-error3{{missing ',' between base or member initializers}}
+// 
expected-error@-1{{unexpected '::new' in member initializer list}}
+// 
expected-error@-2{{unexpected '::delete' in member initializer list}}
+};


Index: lib/Parse/ParseDeclCXX.cpp
===
--- lib/Parse/ParseDeclCXX.cpp
+++ lib/Parse/ParseDeclCXX.cpp
@@ -3237,6 +3237,20 @@
   CXXScopeSpec SS;
   ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
   ParsedType TemplateTypeTy;
+  // If ::new or ::delete was met, ParseOptionalCXXScopeSpecifier just left
+  // them untouched. Diagnose it now to prevent infinite loop on parsing such
+  // code: "f() : ::new".
+  if (Tok.is(tok::coloncolon)) {
+tok::TokenKind NextKind = NextToken().getKind();
+if (NextKind == tok::kw_new || NextKind == tok::kw_delete) {
+  SourceRange Range(Tok.getLocation(), NextToken().getEndLoc());
+  Diag(Tok.getLocation(), diag::err_unexpected_in_member_initlist)
+  << (NextKind == tok::kw_delete) << Range;
+  ConsumeToken(); // the '::' token.
+  ConsumeToken(); // 'new' or 'delete'.
+  return true;
+}
+  }
   if (Tok.is(tok::annot_template_id)) {
 TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
 if (TemplateId->Kind == TNK_Type_template ||
Index: include/clang/Basic/DiagnosticParseKinds.td
===
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -161,6 +161,8 @@
 def err_at_defs_cxx : Error<"@defs is not supported in Objective-C++">;
 def err_at_in_class : Error<"unexpected '@' in member specification">;
 def err_un

[PATCH] D16219: PR8901: attribute "mode" rejected for enums and dependent types

2016-01-15 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla created this revision.
d.zobnin.bugzilla added a reviewer: aaron.ballman.
d.zobnin.bugzilla added a subscriber: cfe-commits.

Allow "mode" attribute for enum types, except for vector modes, for 
compatibility with GCC. Support "mode" attribute with dependent types.

http://reviews.llvm.org/D16219

Files:
  include/clang/Basic/Attr.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/AttributeList.h
  include/clang/Sema/Sema.h
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaTemplateInstantiateDecl.cpp
  test/CodeGen/attr-mode-enums.c
  test/CodeGenCXX/attr-mode-vector-types-tmpl.cpp
  test/Sema/attr-mode-enums.c
  test/Sema/attr-mode.c
  test/SemaCXX/attr-mode-tmpl.cpp

Index: lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -227,6 +227,14 @@
 Attr.getSpellingListIndex());
 }
 
+static void
+instantiateDependentModeAttr(Sema &S,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ const ModeAttr &Attr, Decl *New) {
+  S.AddModeAttr(Attr.getRange(), New, Attr.getMode(),
+Attr.getSpellingListIndex(), /*InInstantiation=*/true);
+}
+
 void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
 const Decl *Tmpl, Decl *New,
 LateInstantiatedAttrVec *LateAttrs,
@@ -265,6 +273,11 @@
   continue;
 }
 
+if (const ModeAttr *Mode = dyn_cast(TmplAttr)) {
+  instantiateDependentModeAttr(*this, TemplateArgs, *Mode, New);
+  continue;
+}
+
 // Existing DLL attribute on the instantiation takes precedence.
 if (TmplAttr->getKind() == attr::DLLExport ||
 TmplAttr->getKind() == attr::DLLImport) {
Index: lib/Sema/SemaDeclAttr.cpp
===
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -3293,6 +3293,8 @@
 /// attribute.
 static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth,
  bool &IntegerMode, bool &ComplexMode) {
+  IntegerMode = true;
+  ComplexMode = false;
   switch (Str.size()) {
   case 2:
 switch (Str[0]) {
@@ -3359,9 +3361,15 @@
   }
 
   IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident;
-  StringRef Str = Name->getName();
 
+  S.AddModeAttr(Attr.getRange(), D, Name, Attr.getAttributeSpellingListIndex());
+}
+
+void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
+   unsigned SpellingListIndex, bool InInstantiation) {
+  StringRef Str = Name->getName();
   normalizeName(Str);
+  SourceLocation AttrLoc = AttrRange.getBegin();
 
   unsigned DestWidth = 0;
   bool IntegerMode = true;
@@ -3377,99 +3385,126 @@
 if (VectorStringLength &&
 !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) &&
 VectorSize.isPowerOf2()) {
-  parseModeAttrArg(S, Str.substr(VectorStringLength + 1), DestWidth,
+  parseModeAttrArg(*this, Str.substr(VectorStringLength + 1), DestWidth,
IntegerMode, ComplexMode);
-  S.Diag(Attr.getLoc(), diag::warn_vector_mode_deprecated);
+  // Avoid duplicate warning from template instantiation.
+  if (!InInstantiation)
+Diag(AttrLoc, diag::warn_vector_mode_deprecated);
 } else {
   VectorSize = 0;
 }
   }
 
   if (!VectorSize)
-parseModeAttrArg(S, Str, DestWidth, IntegerMode, ComplexMode);
+parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode);
+
+  // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
+  // and friends, at least with glibc.
+  // FIXME: Make sure floating-point mappings are accurate
+  // FIXME: Support XF and TF types
+  if (!DestWidth) {
+Diag(AttrLoc, diag::err_machine_mode) << 0 /*Unknown*/ << Name;
+return;
+  }
 
   QualType OldTy;
   if (TypedefNameDecl *TD = dyn_cast(D))
 OldTy = TD->getUnderlyingType();
-  else
+  else if (EnumDecl *ED = dyn_cast(D)) {
+// Something like 'typedef enum { X } __attribute__((mode(XX))) T;'.
+// Try to get type from enum declaration, default to int.
+OldTy = ED->getIntegerType();
+if (OldTy.isNull())
+  OldTy = Context.IntTy;
+  } else
 OldTy = cast(D)->getType();
 
+  if (OldTy->isDependentType()) {
+D->addAttr(::new (Context)
+   ModeAttr(AttrRange, Context, Name, SpellingListIndex));
+return;
+  }
+
   // Base type can also be a vector type (see PR17453).
   // Distinguish between base type and base element type.
   QualType OldElemTy = OldTy;
   if (const VectorType *VT = OldTy->getAs())
 OldElemTy = VT->getElementType();
 
-  if (!OldElemTy->getAs() && !OldElemTy->isComplexType())
-S.Diag(Attr.getLoc(), diag::err_mode_not_primitive);
+  // GCC allows 'mode' attribute on enumeration types (even 

Re: [PATCH] D13285: Fix for bug 24196: clang fails on assertion on complex doubles multiplication when EH is enabled

2016-01-19 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla abandoned this revision.
d.zobnin.bugzilla added a comment.

This issue is fixed in http://reviews.llvm.org/rL253926.


http://reviews.llvm.org/D13285



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D16216: Fix infinite loop when ::new or ::delete are found in member initializer list

2016-01-19 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla updated this revision to Diff 45295.
d.zobnin.bugzilla added a comment.

Thank you for the review! Updated the patch: parser now skips the rest of the 
initializers if the previous one was invalid, added several checks to the test.


http://reviews.llvm.org/D16216

Files:
  lib/Parse/ParseDeclCXX.cpp
  test/Parser/cxx-invalid-function-decl.cpp

Index: lib/Parse/ParseDeclCXX.cpp
===
--- lib/Parse/ParseDeclCXX.cpp
+++ lib/Parse/ParseDeclCXX.cpp
@@ -3187,28 +3187,30 @@
   Actions.CodeCompleteConstructorInitializer(ConstructorDecl,
  MemInitializers);
   return cutOffParsing();
-} else {
-  MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);
-  if (!MemInit.isInvalid())
-MemInitializers.push_back(MemInit.get());
-  else
-AnyErrors = true;
 }
-
+
+MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);
+if (!MemInit.isInvalid())
+  MemInitializers.push_back(MemInit.get());
+else
+  AnyErrors = true;
+
 if (Tok.is(tok::comma))
   ConsumeToken();
 else if (Tok.is(tok::l_brace))
   break;
-// If the next token looks like a base or member initializer, assume that
-// we're just missing a comma.
-else if (Tok.isOneOf(tok::identifier, tok::coloncolon)) {
+// If the previous initializer was valid and the next token looks like a
+// base or member initializer, assume that we're just missing a comma.
+else if (!MemInit.isInvalid() &&
+ Tok.isOneOf(tok::identifier, tok::coloncolon)) {
   SourceLocation Loc = PP.getLocForEndOfToken(PrevTokLocation);
   Diag(Loc, diag::err_ctor_init_missing_comma)
 << FixItHint::CreateInsertion(Loc, ", ");
 } else {
   // Skip over garbage, until we get to '{'.  Don't eat the '{'.
-  Diag(Tok.getLocation(), diag::err_expected_either) << tok::l_brace
- << tok::comma;
+  if (!MemInit.isInvalid())
+Diag(Tok.getLocation(), diag::err_expected_either) << tok::l_brace
+   << tok::comma;
   SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);
   break;
 }
Index: test/Parser/cxx-invalid-function-decl.cpp
===
--- test/Parser/cxx-invalid-function-decl.cpp
+++ test/Parser/cxx-invalid-function-decl.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// Check that "::new" and "::delete" in member initializer list are diagnosed
+// correctly and don't lead to infinite loop on parsing.
+
+// Error: X() (initializer on non-constructor), "::new" is skipped.
+void f1() : X() ::new{}; // expected-error{{only constructors take base 
initializers}}
+
+// Errors: first "::delete" and initializer on non-constructor, others skipped.
+void f2() : ::delete, ::new, X() ::new ::delete{} // expected-error{{expected 
class member or base class name}}
+  // expected-error@-1{{only 
constructors take base initializers}}
+
+// Errors: the '::' token, "::delete" and initializer on non-constructor, 
others skipped.
+void f3() : ::, ::delete X(), ::new {}; // expected-error2{{expected class 
member or base class name}}
+// expected-error@-1{{only 
constructors take base initializers}}
+
+template 
+struct Base1 {
+  T x1;
+  Base1(T a1) : x1(a1) {}
+};
+
+template 
+struct Base2 {
+  T x2;
+  Base2(T a2) : x2(a2) {}
+};
+
+struct S : public Base1, public Base2 {
+  int x;
+
+  // 1-st initializer is correct (just missing ','), 2-nd incorrect, skip 
other.
+  S() : ::Base1(0) ::new, ::Base2(1.0) ::delete x(2) {} // 
expected-error{{expected class member or base class name}}
+// 
expected-error@-1{{missing ',' between base or member initializers}}
+
+  // 1-st and 2-nd are correct, errors: '::' and "::new", others skipped.
+  S(int a) : Base1(a), ::Base2(1.0), ::, // 
expected-error{{expected class member or base class name}}
+ ::new, ! ::delete, ::Base2<() x(3) {}   // 
expected-error{{expected class member or base class name}}
+
+  // All initializers are correct, nothing to skip, diagnose 2 missing commas.
+  S(const S &) : Base1(0) ::Base2(1.0) x(2) {} // 
expected-error2{{missing ',' between base or member initializers}}
+};


Index: lib/Parse/ParseDeclCXX.cpp
===
--- lib/Parse/ParseDeclCXX.cpp
+++ lib/Parse/ParseDeclCXX.cpp
@@ -3187,28 +3187,30 @@
   Actions.CodeCompleteConstructorInitializer(ConstructorDecl,
  MemInitializers);
   return cutOffParsing();
-} else {
-  MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);

Re: [PATCH] D16216: Fix infinite loop when ::new or ::delete are found in member initializer list

2016-01-19 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla added a subscriber: ABataev.
d.zobnin.bugzilla added a comment.

I am going to ask @ABataev to commit this. Hope to get commit access soon (this 
is my 5th patch) :)


http://reviews.llvm.org/D16216



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D16219: PR8901: attribute "mode" rejected for enums and dependent types

2016-01-20 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla updated this revision to Diff 45401.
d.zobnin.bugzilla added a comment.

Updated the patch after committed fix for http://reviews.llvm.org/D16301 
(r258213).

This patch:

1. Adds "Enum" Subject to 'mode' attribute to be able to compile code like 
"typedef enum { X } __attribute__((mode(QI))) T;"
2. Moves handling of the attribute to a new Sema's method in order to support 
'mode' attribute on dependent types;
3. Adds several cases to the tests (both for templates and non-dependent types).

Please take a look.


http://reviews.llvm.org/D16219

Files:
  include/clang/Basic/Attr.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/AttributeList.h
  include/clang/Sema/Sema.h
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaTemplateInstantiateDecl.cpp
  test/CodeGen/attr-mode-enums.c
  test/CodeGenCXX/attr-mode-vector-types-tmpl.cpp
  test/Sema/attr-mode-enums.c
  test/Sema/attr-mode.c
  test/SemaCXX/attr-mode-tmpl.cpp

Index: lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -227,6 +227,14 @@
 Attr.getSpellingListIndex());
 }
 
+static void
+instantiateDependentModeAttr(Sema &S,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ const ModeAttr &Attr, Decl *New) {
+  S.AddModeAttr(Attr.getRange(), New, Attr.getMode(),
+Attr.getSpellingListIndex(), /*InInstantiation=*/true);
+}
+
 void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
 const Decl *Tmpl, Decl *New,
 LateInstantiatedAttrVec *LateAttrs,
@@ -265,6 +273,11 @@
   continue;
 }
 
+if (const ModeAttr *Mode = dyn_cast(TmplAttr)) {
+  instantiateDependentModeAttr(*this, TemplateArgs, *Mode, New);
+  continue;
+}
+
 // Existing DLL attribute on the instantiation takes precedence.
 if (TmplAttr->getKind() == attr::DLLExport ||
 TmplAttr->getKind() == attr::DLLImport) {
Index: lib/Sema/SemaDeclAttr.cpp
===
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -3293,6 +3293,8 @@
 /// attribute.
 static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth,
  bool &IntegerMode, bool &ComplexMode) {
+  IntegerMode = true;
+  ComplexMode = false;
   switch (Str.size()) {
   case 2:
 switch (Str[0]) {
@@ -3359,9 +3361,15 @@
   }
 
   IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident;
-  StringRef Str = Name->getName();
 
+  S.AddModeAttr(Attr.getRange(), D, Name, Attr.getAttributeSpellingListIndex());
+}
+
+void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
+   unsigned SpellingListIndex, bool InInstantiation) {
+  StringRef Str = Name->getName();
   normalizeName(Str);
+  SourceLocation AttrLoc = AttrRange.getBegin();
 
   unsigned DestWidth = 0;
   bool IntegerMode = true;
@@ -3377,99 +3385,126 @@
 if (VectorStringLength &&
 !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) &&
 VectorSize.isPowerOf2()) {
-  parseModeAttrArg(S, Str.substr(VectorStringLength + 1), DestWidth,
+  parseModeAttrArg(*this, Str.substr(VectorStringLength + 1), DestWidth,
IntegerMode, ComplexMode);
-  S.Diag(Attr.getLoc(), diag::warn_vector_mode_deprecated);
+  // Avoid duplicate warning from template instantiation.
+  if (!InInstantiation)
+Diag(AttrLoc, diag::warn_vector_mode_deprecated);
 } else {
   VectorSize = 0;
 }
   }
 
   if (!VectorSize)
-parseModeAttrArg(S, Str, DestWidth, IntegerMode, ComplexMode);
+parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode);
+
+  // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
+  // and friends, at least with glibc.
+  // FIXME: Make sure floating-point mappings are accurate
+  // FIXME: Support XF and TF types
+  if (!DestWidth) {
+Diag(AttrLoc, diag::err_machine_mode) << 0 /*Unknown*/ << Name;
+return;
+  }
 
   QualType OldTy;
   if (TypedefNameDecl *TD = dyn_cast(D))
 OldTy = TD->getUnderlyingType();
-  else
+  else if (EnumDecl *ED = dyn_cast(D)) {
+// Something like 'typedef enum { X } __attribute__((mode(XX))) T;'.
+// Try to get type from enum declaration, default to int.
+OldTy = ED->getIntegerType();
+if (OldTy.isNull())
+  OldTy = Context.IntTy;
+  } else
 OldTy = cast(D)->getType();
 
+  if (OldTy->isDependentType()) {
+D->addAttr(::new (Context)
+   ModeAttr(AttrRange, Context, Name, SpellingListIndex));
+return;
+  }
+
   // Base type can also be a vector type (see PR17453).
   // Distinguish between base type and base element type.
   QualType OldElemTy = OldTy;
   if (const V

Re: [PATCH] D16219: PR8901: attribute "mode" rejected for enums and dependent types

2016-01-27 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla added a comment.

Friendly ping, please take a look.


http://reviews.llvm.org/D16219



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D16630: PR23057: Fix assertion `Val && "isa<> used on a null pointer"' on invalid for-range expression

2016-01-27 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla created this revision.
d.zobnin.bugzilla added reviewers: kcc, rsmith.
d.zobnin.bugzilla added a subscriber: cfe-commits.

Fix the issue discovered by fuzzing 
(https://llvm.org/bugs/show_bug.cgi?id=23057#c18) by handling nullptr in 
Sema::ActOnCXXForRangeDecl and correct delayed typos in for-range expression 
before calling Sema::ActOnCXXForRangeStmt (fixes PR26288 as well).

http://reviews.llvm.org/D16630

Files:
  lib/Parse/ParseStmt.cpp
  lib/Sema/SemaDecl.cpp
  test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp
  test/Parser/cxx-invalid-for-range.cpp

Index: lib/Parse/ParseStmt.cpp
===
--- lib/Parse/ParseStmt.cpp
+++ lib/Parse/ParseStmt.cpp
@@ -1716,9 +1716,11 @@
   StmtResult ForEachStmt;
 
   if (ForRange) {
+ExprResult CorrectedRange =
+Actions.CorrectDelayedTyposInExpr(ForRangeInit.RangeExpr.get());
 ForRangeStmt = Actions.ActOnCXXForRangeStmt(
 getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(),
-ForRangeInit.ColonLoc, ForRangeInit.RangeExpr.get(),
+ForRangeInit.ColonLoc, CorrectedRange.get(),
 T.getCloseLocation(), Sema::BFRK_Build);
 
   // Similarly, we need to do the semantic analysis for a for-range
Index: lib/Sema/SemaDecl.cpp
===
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -9901,6 +9901,10 @@
 }
 
 void Sema::ActOnCXXForRangeDecl(Decl *D) {
+  // If there is no declaration, there was an error parsing it. Ignore it.
+  if (!D)
+return;
+
   VarDecl *VD = dyn_cast(D);
   if (!VD) {
 Diag(D->getLocation(), diag::err_for_range_decl_must_be_var);
Index: test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp
===
--- test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp
+++ test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp
@@ -18,6 +18,9 @@
   for (struct S { S(int) {} } s : arr) { // expected-error {{types may not be 
defined in a for range declaration}}
   }
 
+  for (struct S { S(int) {} } s : Undeclared); // expected-error{{types may 
not be defined in a for range declaration}}
+   // expected-error@-1{{use of 
undeclared identifier 'Undeclared'}}
+
   new struct T {}; // expected-error {{'T' cannot be defined in a type 
specifier}}
   new struct A {}; // expected-error {{'A' cannot be defined in a type 
specifier}}
 
Index: test/Parser/cxx-invalid-for-range.cpp
===
--- test/Parser/cxx-invalid-for-range.cpp
+++ test/Parser/cxx-invalid-for-range.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+// From PR23057 comment #18 (https://llvm.org/bugs/show_bug.cgi?id=23057#c18).
+
+namespace N {
+  int X[10]; // expected-note{{declared here
+}
+
+void f1() {
+  for (auto operator new : X); // expected-error{{'operator new' cannot be the 
name of a variable or data member}}
+   // expected-error@-1{{use of undeclared 
identifier 'X'; did you mean 'N::X'?}}
+}
+
+void f2() {
+  for (a operator== :) // expected-error{{'operator==' cannot be the name of a 
variable or data member}}
+   // expected-error@-1{{expected expression}}
+   // expected-error@-2{{unknown type name 'a'}}
+} // expected-error{{expected statement}}


Index: lib/Parse/ParseStmt.cpp
===
--- lib/Parse/ParseStmt.cpp
+++ lib/Parse/ParseStmt.cpp
@@ -1716,9 +1716,11 @@
   StmtResult ForEachStmt;
 
   if (ForRange) {
+ExprResult CorrectedRange =
+Actions.CorrectDelayedTyposInExpr(ForRangeInit.RangeExpr.get());
 ForRangeStmt = Actions.ActOnCXXForRangeStmt(
 getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(),
-ForRangeInit.ColonLoc, ForRangeInit.RangeExpr.get(),
+ForRangeInit.ColonLoc, CorrectedRange.get(),
 T.getCloseLocation(), Sema::BFRK_Build);
 
   // Similarly, we need to do the semantic analysis for a for-range
Index: lib/Sema/SemaDecl.cpp
===
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -9901,6 +9901,10 @@
 }
 
 void Sema::ActOnCXXForRangeDecl(Decl *D) {
+  // If there is no declaration, there was an error parsing it. Ignore it.
+  if (!D)
+return;
+
   VarDecl *VD = dyn_cast(D);
   if (!VD) {
 Diag(D->getLocation(), diag::err_for_range_decl_must_be_var);
Index: test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp
===
--- test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp
+++ test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp
@@ -18,6 +18,9 @@
   for (struct S { S(int) {} } s : arr) { // expected-error {{types may not be defined in a for range declaration}}
   }
 
+  for (struct S { S(int) {} } s : Undeclared); // expected-error{{types may not be define

Re: [PATCH] D14467: [MS] Fix for bug 25013 - #pragma vtordisp is unknown inside functions.

2015-11-17 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla updated this revision to Diff 40380.
d.zobnin.bugzilla added a comment.

Only tests have been updated: enabled a test case for Sema, which pass with 
these changes, added corresponding test case for CodeGen.


http://reviews.llvm.org/D14467

Files:
  include/clang/Sema/Sema.h
  lib/Parse/ParseDeclCXX.cpp
  lib/Parse/ParseStmt.cpp
  test/Layout/ms-vtordisp-local.cpp
  test/SemaCXX/pragma-vtordisp.cpp

Index: lib/Parse/ParseDeclCXX.cpp
===
--- lib/Parse/ParseDeclCXX.cpp
+++ lib/Parse/ParseDeclCXX.cpp
@@ -2854,6 +2854,11 @@
 return DeclGroupPtrTy();
   }
 
+  if (Tok.is(tok::annot_pragma_ms_vtordisp)) {
+HandlePragmaMSVtorDisp();
+return DeclGroupPtrTy();
+  }
+
   // If we see a namespace here, a close brace was missing somewhere.
   if (Tok.is(tok::kw_namespace)) {
 DiagnoseUnexpectedNamespace(cast(TagDecl));
Index: lib/Parse/ParseStmt.cpp
===
--- lib/Parse/ParseStmt.cpp
+++ lib/Parse/ParseStmt.cpp
@@ -358,6 +358,11 @@
 HandlePragmaMSPragma();
 return StmtEmpty();
 
+  case tok::annot_pragma_ms_vtordisp:
+ProhibitAttributes(Attrs);
+HandlePragmaMSVtorDisp();
+return StmtEmpty();
+
   case tok::annot_pragma_loop_hint:
 ProhibitAttributes(Attrs);
 return ParsePragmaLoopHint(Stmts, OnlyStatement, TrailingElseLoc, Attrs);
@@ -885,6 +890,9 @@
 case tok::annot_pragma_ms_pragma:
   HandlePragmaMSPragma();
   break;
+case tok::annot_pragma_ms_vtordisp:
+  HandlePragmaMSVtorDisp();
+  break;
 default:
   checkForPragmas = false;
   break;
@@ -1895,6 +1903,11 @@
   PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc,
   "parsing function body");
 
+  // Save and reset current vtordisp stack if we have entered a C++ method body.
+  bool IsCXXMethod =
+  getLangOpts().CPlusPlus && Decl && isa(Decl);
+  Sema::VtorDispStackRAII SavedVtorDispStack(Actions, IsCXXMethod);
+
   // Do not enter a scope for the brace, as the arguments are in the same scope
   // (the function body) as the body itself.  Instead, just read the statement
   // list and put it into a CompoundStmt for safe keeping.
@@ -1934,6 +1947,11 @@
 return Actions.ActOnSkippedFunctionBody(Decl);
   }
 
+  // Save and reset current vtordisp stack if we have entered a C++ method body.
+  bool IsCXXMethod =
+  getLangOpts().CPlusPlus && Decl && isa(Decl);
+  Sema::VtorDispStackRAII SavedVtorDispStack(Actions, IsCXXMethod);
+
   SourceLocation LBraceLoc = Tok.getLocation();
   StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc, /*FnTry*/true));
   // If we failed to parse the try-catch, we just give the function an empty
Index: include/clang/Sema/Sema.h
===
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -1007,6 +1007,24 @@
 bool OldFPContractState : 1;
   };
 
+  /// Records and restores the vtordisp state on entry/exit of C++ method body.
+  class VtorDispStackRAII {
+  public:
+VtorDispStackRAII(Sema &S, bool ShouldSaveAndRestore)
+  : S(S), ShouldSaveAndRestore(ShouldSaveAndRestore), OldVtorDispStack() {
+  if (ShouldSaveAndRestore)
+OldVtorDispStack = S.VtorDispModeStack;
+}
+~VtorDispStackRAII() {
+  if (ShouldSaveAndRestore)
+S.VtorDispModeStack = OldVtorDispStack;
+}
+  private:
+Sema &S;
+bool ShouldSaveAndRestore;
+SmallVector OldVtorDispStack;
+  };
+
   void addImplicitTypedef(StringRef Name, QualType T);
 
 public:
Index: test/Layout/ms-vtordisp-local.cpp
===
--- test/Layout/ms-vtordisp-local.cpp
+++ test/Layout/ms-vtordisp-local.cpp
@@ -0,0 +1,217 @@
+// RUN: %clang_cc1 -fms-extensions -fexceptions -fcxx-exceptions -emit-llvm-only -triple x86_64-pc-win32 -fdump-record-layouts -fsyntax-only %s 2>&1 | FileCheck %s
+
+struct Base {
+  virtual ~Base() {}
+  virtual void BaseFunc() {}
+};
+
+#pragma vtordisp(0)
+
+struct Container {
+  static void f() try {
+#pragma vtordisp(2)
+struct HasVtorDisp : virtual Base {
+  virtual ~HasVtorDisp() {}
+  virtual void Func() {}
+};
+
+int x[sizeof(HasVtorDisp)];
+
+// HasVtorDisp: vtordisp because of pragma right before it.
+//
+// CHECK: *** Dumping AST Record Layout
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT:  0 | struct HasVtorDisp
+// CHECK-NEXT:  0 |   (HasVtorDisp vftable pointer)
+// CHECK-NEXT:  8 |   (HasVtorDisp vbtable pointer)
+// CHECK-NEXT: 20 |   (vtordisp for vbase Base)
+// CHECK-NEXT: 24 |   struct Base (virtual base)
+// CHECK-NEXT: 24 | (Base vftable pointer)
+// CHECK-NEXT:| [sizeof=32, align=8,
+// CHECK-NEXT:|  nvsize=16, nvalign=8]
+  } catch (...) {
+  }
+};

Re: [PATCH] D14467: [MS] Fix for bug 25013 - #pragma vtordisp is unknown inside functions.

2015-11-17 Thread Denis Zobnin via cfe-commits
d.zobnin.bugzilla added inline comments.


Comment at: test/SemaCXX/pragma-vtordisp.cpp:34-35
@@ -33,6 +33,4 @@
 
 struct C {
-// FIXME: Our implementation based on token insertion makes it impossible for
-// the pragma to appear everywhere we should support it.
-//#pragma vtordisp()
+#pragma vtordisp()
   struct D : virtual A {

Yes, we can. Enabled this case, it passes with these changes.


http://reviews.llvm.org/D14467



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits