diff --git a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/UnusedSymbolInFileScopeChecker.java b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/UnusedSymbolInFileScopeChecker.java
index b22e9f26902..9c34d78659a 100644
--- a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/UnusedSymbolInFileScopeChecker.java
+++ b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/UnusedSymbolInFileScopeChecker.java
@@ -48,6 +48,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer;
 import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
 import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
 import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
+import org.eclipse.cdt.core.parser.util.AttributeUtil;
 
 /**
  * Checker looking for unused function or variable declarations.
@@ -58,6 +59,7 @@ public class UnusedSymbolInFileScopeChecker extends AbstractIndexAstChecker {
 	public static final String ER_UNUSED_STATIC_FUNCTION_ID = "org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem"; //$NON-NLS-1$
 	public static final String PARAM_MACRO_ID = "macro"; //$NON-NLS-1$
 	public static final String PARAM_EXCEPT_ARG_LIST = "exceptions"; //$NON-NLS-1$
+	private static final String[] ATTRIBUTE_UNUSED = new String[] { "__unused__", "unused" };  //$NON-NLS-1$//$NON-NLS-2$
 
 	private Map<IBinding, IASTDeclarator> externFunctionDeclarations = new HashMap<IBinding, IASTDeclarator>();
 	private Map<IBinding, IASTDeclarator> staticFunctionDeclarations = new HashMap<IBinding, IASTDeclarator>();
@@ -130,6 +132,8 @@ public class UnusedSymbolInFileScopeChecker extends AbstractIndexAstChecker {
 
 						IASTDeclarator[] declarators = simpleDeclaration.getDeclarators();
 						for (IASTDeclarator decl : declarators) {
+							if (AttributeUtil.hasAttribute(decl, ATTRIBUTE_UNUSED))
+								continue;
 							IASTName astName = decl.getName();
 							if (astName != null) {
 								IBinding binding = astName.resolveBinding();
@@ -191,14 +195,15 @@ public class UnusedSymbolInFileScopeChecker extends AbstractIndexAstChecker {
 						// definitions
 						IASTFunctionDefinition definition = (IASTFunctionDefinition) element;
 
-						IASTName astName = definition.getDeclarator().getName();
+						IASTFunctionDeclarator declarator = definition.getDeclarator();
+						IASTName astName = declarator.getName();
 						if (astName != null) {
 							IBinding binding = astName.resolveBinding();
 
-							if (definition.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_static) {
-								if (!(astName instanceof ICPPASTQualifiedName)) {
-									staticFunctionDefinitions.put(binding, definition.getDeclarator());
-								}
+							if (definition.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_static &&
+									!(astName instanceof ICPPASTQualifiedName) &&
+									!AttributeUtil.hasAttribute(declarator, ATTRIBUTE_UNUSED)) {
+								staticFunctionDefinitions.put(binding, declarator);
 							}
 
 							// externFunctionDeclarators filter out
diff --git a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/UnusedSymbolInFileScopeCheckerTest.java b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/UnusedSymbolInFileScopeCheckerTest.java
index 4cd1d7964fa..7bb967ed071 100644
--- a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/UnusedSymbolInFileScopeCheckerTest.java
+++ b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/UnusedSymbolInFileScopeCheckerTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2011 Andrew Gvozdev and others.
+ * Copyright (c) 2011, 2012 Andrew Gvozdev and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -307,4 +307,14 @@ public class UnusedSymbolInFileScopeCheckerTest extends CheckerTestCase {
 		checkNoErrors();
 	}
 
+	// static int v1 __attribute__((unused));
+	// int f1() __attribute__((__unused__));
+	// extern int f2() __attribute__((unused));
+	// static void f3() __attribute__((unused));
+	// static void f4() __attribute__((unused));
+	// static void f4() __attribute__((unused)) {}
+	public void testAttributeUnused() throws IOException {
+		loadCodeAndRun(getAboveComment());
+		checkNoErrors();
+	}
 }
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/AttributeUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/AttributeUtil.java
new file mode 100644
index 00000000000..53c22374665
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/AttributeUtil.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Google, Inc and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * 	   Sergey Prigogin (Google) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.core.parser.util;
+
+import org.eclipse.cdt.core.dom.ast.IASTAttribute;
+import org.eclipse.cdt.core.dom.ast.IASTAttributeOwner;
+import org.eclipse.cdt.core.dom.ast.IASTToken;
+
+/**
+ * Collection of static methods for dealing with attributes.
+ * @see org.eclipse.cdt.core.dom.ast.IASTAttribute
+ * @see org.eclipse.cdt.core.dom.ast.IASTAttributeOwner
+ * @since 5.4
+ */
+public class AttributeUtil {
+	private static final String[] ATTRIBUTE_NORETURN = new String[] { "__noreturn__", "noreturn" };  //$NON-NLS-1$//$NON-NLS-2$
+
+	// Not instantiatable.
+	private AttributeUtil() {}
+
+	/**
+	 * Returns {@code true} if a declarator has an attribute with one of the given names.
+	 * The {@code names} array is assumed to be small. 
+	 */
+	public static boolean hasAttribute(IASTAttributeOwner node, String[] names) {
+	    IASTAttribute[] attributes = node.getAttributes();
+		for (IASTAttribute attribute : attributes) {
+			char[] name = attribute.getName();
+			for (int i = 0; i < names.length; i++) {
+				if (CharArrayUtils.equals(name, names[i]))
+					return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Returns {@code true} if the node has a "noreturn" or "__noreturn__" attribute.
+	 */
+	public static boolean hasNoreturnAttribute(IASTAttributeOwner node) {
+		return hasAttribute(node, ATTRIBUTE_NORETURN);
+	}
+
+	/**
+	 * Returns character representation of the attribute argument, or {@code null} if the attribute
+	 * has zero or more than one argument.
+	 */
+	public static char[] getSimpleArgument(IASTAttribute attribute) {
+		IASTToken argumentClause = attribute.getArgumentClause();
+		return argumentClause == null ? null : argumentClause.getTokenCharImage();
+	}
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAttribute.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAttribute.java
index d1093ea9347..7cb00efe5c2 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAttribute.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAttribute.java
@@ -12,16 +12,12 @@ package org.eclipse.cdt.internal.core.dom.parser;
 
 import org.eclipse.cdt.core.dom.ast.ASTVisitor;
 import org.eclipse.cdt.core.dom.ast.IASTAttribute;
-import org.eclipse.cdt.core.dom.ast.IASTAttributeOwner;
 import org.eclipse.cdt.core.dom.ast.IASTToken;
-import org.eclipse.cdt.core.parser.util.CharArrayUtils;
 
 /**
  * Base class for C and C++ attributes.
  */
 public abstract class ASTAttribute extends ASTNode implements IASTAttribute {
-	private static final String[] NORETURN_ATTRIBUTES = new String[] { "__noreturn__", "noreturn" };  //$NON-NLS-1$//$NON-NLS-2$
-
     private final char[] name;
     private final IASTToken argumentClause;
 
@@ -66,38 +62,4 @@ public abstract class ASTAttribute extends ASTNode implements IASTAttribute {
 
         return true;
     }
-
-	/**
-	 * Returns {@code true} if a declarator has an attribute with one of the given names.
-	 * The {@code names} array is assumed to be small. 
-	 */
-	public static boolean hasAttribute(IASTAttributeOwner node, String[] names) {
-	    IASTAttribute[] attributes = node.getAttributes();
-		for (IASTAttribute attribute : attributes) {
-			char[] name = attribute.getName();
-			for (int i = 0; i < names.length; i++) {
-				if (CharArrayUtils.equals(name, names[i]))
-					return true;
-			}
-		}
-		return false;
-	}
-
-	/**
-	 * Returns {@code true} if the node has a "noreturn" or "__noreturn__" attribute.
-	 */
-	public static boolean hasNoreturnAttribute(IASTAttributeOwner node) {
-		return hasAttribute(node, NORETURN_ATTRIBUTES);
-	}
-
-	/**
-	 * Returns character representation of the attribute argument, or {@code null} if the attribute
-	 * has zero or more than one argument.
-	 */
-	public static char[] getSimpleArgument(IASTAttribute attribute) {
-		IASTToken argumentClause = attribute.getArgumentClause();
-		if (argumentClause == null)
-			return null;
-		return argumentClause.getTokenCharImage();
-	}
 }
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CFunction.java
index 937a2dd0c6d..16362419e82 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CFunction.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CFunction.java
@@ -33,6 +33,7 @@ import org.eclipse.cdt.core.dom.ast.IScope;
 import org.eclipse.cdt.core.dom.ast.IType;
 import org.eclipse.cdt.core.dom.ast.gnu.c.ICASTKnRFunctionDeclarator;
 import org.eclipse.cdt.core.parser.util.ArrayUtil;
+import org.eclipse.cdt.core.parser.util.AttributeUtil;
 import org.eclipse.cdt.core.parser.util.CharArrayUtils;
 import org.eclipse.cdt.internal.core.dom.Linkage;
 import org.eclipse.cdt.internal.core.dom.parser.ASTAttribute;
@@ -488,7 +489,7 @@ public class CFunction extends PlatformObject implements IFunction, ICInternalFu
 	@Override
 	public boolean isNoReturn() {
 		IASTFunctionDeclarator dtor = getPreferredDtor();
-		return dtor != null && ASTAttribute.hasNoreturnAttribute(dtor);
+		return dtor != null && AttributeUtil.hasNoreturnAttribute(dtor);
 	}
 
 	protected IASTFunctionDeclarator getPreferredDtor() {
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java
index 520b9143c09..387e509d4c6 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java
@@ -90,6 +90,7 @@ import org.eclipse.cdt.core.dom.ast.gnu.c.ICASTKnRFunctionDeclarator;
 import org.eclipse.cdt.core.index.IIndexBinding;
 import org.eclipse.cdt.core.index.IIndexFileSet;
 import org.eclipse.cdt.core.parser.util.ArrayUtil;
+import org.eclipse.cdt.core.parser.util.AttributeUtil;
 import org.eclipse.cdt.core.parser.util.CharArraySet;
 import org.eclipse.cdt.core.parser.util.CharArrayUtils;
 import org.eclipse.cdt.core.parser.util.IContentAssistMatcher;
@@ -1272,7 +1273,7 @@ public class CVisitor extends ASTQueries {
 				for (IASTAttribute attribute : attributes) {
 					char[] name = attribute.getName();
 					if (CharArrayUtils.equals(name, "__mode__") || CharArrayUtils.equals(name, "mode")) { //$NON-NLS-1$ //$NON-NLS-2$
-						char[] mode = ASTAttribute.getSimpleArgument(attribute);
+						char[] mode = AttributeUtil.getSimpleArgument(attribute);
 						if (CharArrayUtils.equals(mode, "__QI__") || CharArrayUtils.equals(mode, "QI")) { //$NON-NLS-1$ //$NON-NLS-2$
 							type = new CBasicType(IBasicType.Kind.eChar,
 									basicType.isUnsigned() ? IBasicType.IS_UNSIGNED : IBasicType.IS_SIGNED);
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java
index eee15bb797e..d05977e2226 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java
@@ -45,6 +45,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
 import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
 import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
 import org.eclipse.cdt.core.parser.util.ArrayUtil;
+import org.eclipse.cdt.core.parser.util.AttributeUtil;
 import org.eclipse.cdt.internal.core.dom.Linkage;
 import org.eclipse.cdt.internal.core.dom.parser.ASTAttribute;
 import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
@@ -599,6 +600,6 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt
 	@Override
 	public boolean isNoReturn() {
 		ICPPASTFunctionDeclarator dtor = getPreferredDtor();
-		return dtor != null && ASTAttribute.hasNoreturnAttribute(dtor);
+		return dtor != null && AttributeUtil.hasNoreturnAttribute(dtor);
 	}
 }
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionTemplate.java
index 13bfb745b53..101e4926023 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionTemplate.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionTemplate.java
@@ -36,6 +36,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
 import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
 import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
 import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
+import org.eclipse.cdt.core.parser.util.AttributeUtil;
 import org.eclipse.cdt.internal.core.dom.parser.ASTAttribute;
 import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
 import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
@@ -344,7 +345,7 @@ public class CPPFunctionTemplate extends CPPTemplateDefinition
 	public boolean isNoReturn() {
     	ICPPASTFunctionDeclarator fdecl= getFirstFunctionDtor();
     	if (fdecl != null) {
-    		return ASTAttribute.hasNoreturnAttribute(fdecl);
+    		return AttributeUtil.hasNoreturnAttribute(fdecl);
     	}
         return false;
     }
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java
index 33c65cbd8fa..75218d30195 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java
@@ -156,6 +156,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
 import org.eclipse.cdt.core.index.IIndex;
 import org.eclipse.cdt.core.index.IIndexBinding;
 import org.eclipse.cdt.core.parser.util.ArrayUtil;
+import org.eclipse.cdt.core.parser.util.AttributeUtil;
 import org.eclipse.cdt.core.parser.util.CharArrayUtils;
 import org.eclipse.cdt.internal.core.dom.parser.ASTAttribute;
 import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
@@ -1854,7 +1855,7 @@ public class CPPVisitor extends ASTQueries {
 				for (IASTAttribute attribute : attributes) {
 					char[] name = attribute.getName();
 					if (CharArrayUtils.equals(name, "__mode__") || CharArrayUtils.equals(name, "mode")) { //$NON-NLS-1$ //$NON-NLS-2$
-						char[] mode = ASTAttribute.getSimpleArgument(attribute);
+						char[] mode = AttributeUtil.getSimpleArgument(attribute);
 						if (CharArrayUtils.equals(mode, "__QI__") || CharArrayUtils.equals(mode, "QI")) { //$NON-NLS-1$ //$NON-NLS-2$
 							type = new CPPBasicType(IBasicType.Kind.eChar,
 									basicType.isUnsigned() ? IBasicType.IS_UNSIGNED : IBasicType.IS_SIGNED);